From 6ea3718156fd0a2357ae70c454b5f177efbe8c55 Mon Sep 17 00:00:00 2001 From: Mathias Birrer Date: Thu, 28 Oct 2021 09:31:15 +0200 Subject: [PATCH 1/2] fix: handle error when parsing field with sleep_time: 86400 --- fitparse/processors.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fitparse/processors.py b/fitparse/processors.py index 493f166..268859e 100644 --- a/fitparse/processors.py +++ b/fitparse/processors.py @@ -83,9 +83,18 @@ def process_type_local_date_time(self, field_data): def process_type_localtime_into_day(self, field_data): if field_data.value is not None: - m, s = divmod(field_data.value, 60) - h, m = divmod(m, 60) - field_data.value = datetime.time(h, m, s) + # NOTE: Values larger or equal to 86400 should not be possible. + # Additionally, if the value is exactly 86400, it will lead to an error when trying to + # create the time with datetime.time(24, 0 , 0). + # + # E.g. Garmin does add "sleep_time": 86400 to its fit files, + # which causes an error if not properly handled. + if field_data.value >= 86400: + field_data.value = datetime.time.max + else: + m, s = divmod(field_data.value, 60) + h, m = divmod(m, 60) + field_data.value = datetime.time(h, m, s) field_data.units = None From b4590fd930ce65d5f35c7e418b61aa7aff54ba97 Mon Sep 17 00:00:00 2001 From: Mathias Birrer Date: Fri, 12 Dec 2025 09:56:41 +0100 Subject: [PATCH 2/2] feat: update profile.py to 21.171.00 --- fitparse/profile.py | 13448 ++++++++++++++++++++++++++++-------------- 1 file changed, 8987 insertions(+), 4461 deletions(-) diff --git a/fitparse/profile.py b/fitparse/profile.py index daaf579..647b56b 100644 --- a/fitparse/profile.py +++ b/fitparse/profile.py @@ -1,7 +1,8 @@ + # ***************** BEGIN AUTOMATICALLY GENERATED FIT PROFILE ****************** # *************************** DO NOT EDIT THIS FILE **************************** -# ************ EXPORTED PROFILE FROM SDK VERSION 20.8 ON 2019-03-05 ************ -# ********* PARSED 161 TYPES (2985 VALUES), 85 MESSAGES (1038 FIELDS) ********** +# *********** EXPORTED PROFILE FROM SDK VERSION 21.171 ON 2025-12-12 *********** +# ********* PARSED 198 TYPES (4307 VALUES), 120 MESSAGES (1386 FIELDS) ********* from fitparse.records import ( ComponentField, @@ -94,6 +95,16 @@ 2: 'modern', }, ), + 'ant_channel_id': FieldType( + name='ant_channel_id', + base_type=BASE_TYPES[0x8C], # uint32z + values={ + 0x0000FFFF: 'ant_device_number', + 0x00FF0000: 'ant_device_type', + 0x0F000000: 'ant_transmission_type_lower_nibble', + 0xF0000000: 'ant_extended_device_number_upper_nibble', + }, + ), 'ant_network': FieldType( name='ant_network', base_type=BASE_TYPES[0x00], # enum @@ -121,10 +132,12 @@ 26: 'racquet', 27: 'control_hub', 31: 'muscle_oxygen', + 34: 'shifting', 35: 'bike_light_main', 36: 'bike_light_shared', 38: 'exd', 40: 'bike_radar', + 46: 'bike_aero', 119: 'weight_scale', 120: 'heart_rate', 121: 'bike_speed_cadence', @@ -197,6 +210,7 @@ 4: 'position_waypoint', 5: 'position_marked', 6: 'off', + 13: 'auto_select', }, ), 'autoscroll': FieldType( @@ -229,6 +243,72 @@ 0: 'infinite', # Backlight stays on forever. }, ), + 'banded_exercises_exercise_name': FieldType( + name='banded_exercises_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 1: 'ab_twist', + 2: 'back_extension', + 3: 'bicycle_crunch', + 4: 'calf_raises', + 5: 'chest_press', + 6: 'clam_shells', + 7: 'curl', + 8: 'deadbug', + 9: 'deadlift', + 10: 'donkey_kick', + 11: 'external_rotation', + 12: 'external_rotation_at_90_degree_abduction', + 13: 'face_pull', + 14: 'fire_hydrant', + 15: 'fly', + 16: 'front_raise', + 17: 'glute_bridge', + 18: 'hamstring_curls', + 19: 'high_plank_leg_lifts', + 20: 'hip_extension', + 21: 'internal_rotation', + 22: 'jumping_jack', + 23: 'kneeling_crunch', + 24: 'lateral_band_walks', + 25: 'lateral_raise', + 26: 'latpull', + 27: 'leg_abduction', + 28: 'leg_adduction', + 29: 'leg_extension', + 30: 'lunge', + 31: 'plank', + 32: 'pull_apart', + 33: 'push_ups', + 34: 'reverse_crunch', + 35: 'row', + 36: 'shoulder_abduction', + 37: 'shoulder_extension', + 38: 'shoulder_external_rotation', + 39: 'shoulder_flexion_to_90_degrees', + 40: 'side_plank_leg_lifts', + 41: 'side_raise', + 42: 'squat', + 43: 'squat_to_press', + 44: 'tricep_extension', + 45: 'tricep_kickback', + 46: 'upright_row', + 47: 'wall_crawl_with_external_rotation', + 49: 'lateral_raise_wheelchair', + 50: 'triceps_extension_wheelchair', + 51: 'chest_fly_incline_wheelchair', + 52: 'chest_fly_decline_wheelchair', + 53: 'pull_down_wheelchair', + 54: 'straight_arm_pull_down_wheelchair', + 55: 'curl_wheelchair', + 56: 'overhead_curl_wheelchair', + 57: 'face_pull_wheelchair', + 58: 'around_the_world_wheelchair', + 59: 'pull_apart_wheelchair', + 60: 'side_curl_wheelchair', + 61: 'overhead_press_wheelchair', + }, + ), 'battery_status': FieldType( name='battery_status', base_type=BASE_TYPES[0x02], # uint8 @@ -242,6 +322,40 @@ 7: 'unknown', }, ), + 'battle_rope_exercise_name': FieldType( + name='battle_rope_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'alternating_figure_eight', + 1: 'alternating_jump_wave', + 2: 'alternating_kneeling_to_standing_wave', + 3: 'alternating_lunge_wave', + 4: 'alternating_squat_wave', + 5: 'alternating_wave', + 6: 'alternating_wave_with_lateral_shuffle', + 7: 'clap_wave', + 8: 'double_arm_figure_eight', + 9: 'double_arm_side_to_side_snake', + 10: 'double_arm_side_wave', + 11: 'double_arm_slam', + 12: 'double_arm_wave', + 13: 'grappler_toss', + 14: 'hip_toss', + 15: 'in_and_out_wave', + 16: 'inside_circle', + 17: 'jumping_jacks', + 18: 'outside_circle', + 19: 'rainbow', + 20: 'side_plank_wave', + 21: 'sidewinder', + 22: 'sitting_russian_twist', + 23: 'snake_wave', + 24: 'split_jack', + 25: 'stage_coach', + 26: 'ultimate_warrior', + 27: 'upper_cuts', + }, + ), 'bench_press_exercise_name': FieldType( name='bench_press_exercise_name', base_type=BASE_TYPES[0x84], # uint16 @@ -275,6 +389,15 @@ 26: 'alternating_dumbbell_chest_press', }, ), + 'bike_exercise_name': FieldType( + name='bike_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'bike', + 1: 'ride', + 2: 'sprint', + }, + ), 'bike_light_beam_angle_mode': FieldType( name='bike_light_beam_angle_mode', base_type=BASE_TYPES[0x02], # uint8 @@ -293,6 +416,27 @@ 6: 'trail', }, ), + 'bike_outdoor_exercise_name': FieldType( + name='bike_outdoor_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'bike', + }, + ), + 'ble_device_type': FieldType( + name='ble_device_type', + base_type=BASE_TYPES[0x02], # uint8 + values={ + 0: 'connected_gps', # GPS that is provided over a proprietary bluetooth service + 1: 'heart_rate', + 2: 'bike_power', + 3: 'bike_speed_cadence', + 4: 'bike_speed', + 5: 'bike_cadence', + 6: 'footpod', + 7: 'bike_trainer', # Indoor-Bike FTMS protocol + }, + ), 'body_location': FieldType( name='body_location', base_type=BASE_TYPES[0x00], # enum @@ -436,6 +580,27 @@ 19: 'weighted_squat_jacks', 20: 'triple_under', 21: 'weighted_triple_under', + 22: 'elliptical', + 23: 'spinning', + 24: 'pole_paddle_forward_wheelchair', + 25: 'pole_paddle_backward_wheelchair', + 26: 'pole_handcycle_forward_wheelchair', + 27: 'pole_handcycle_backward_wheelchair', + 28: 'pole_rainbow_wheelchair', + 29: 'double_punch_forward_wheelchair', + 30: 'double_punch_down_wheelchair', + 31: 'double_punch_sideways_wheelchair', + 32: 'double_punch_up_wheelchair', + 33: 'sit_ski_wheelchair', + 34: 'sitting_jacks_wheelchair', + 35: 'punch_forward_wheelchair', + 36: 'punch_down_wheelchair', + 37: 'punch_sideways_wheelchair', + 38: 'punch_up_wheelchair', + 39: 'punch_bag_wheelchair', + 40: 'pole_dd_ff_uu_wheelchair', + 41: 'butterfly_arms_wheelchair', + 42: 'punch', }, ), 'carry_exercise_name': FieldType( @@ -447,6 +612,18 @@ 2: 'farmers_walk_on_toes', 3: 'hex_dumbbell_hold', 4: 'overhead_carry', + 5: 'dumbbell_waiter_carry', + 6: 'farmers_carry_walk_lunge', + 7: 'farmers_carry', + 8: 'farmers_carry_on_toes', + }, + ), + 'ccr_setpoint_switch_mode': FieldType( + name='ccr_setpoint_switch_mode', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'manual', # User switches setpoints manually + 1: 'automatic', # Switch automatically based on depth }, ), 'checksum': FieldType( @@ -454,7 +631,7 @@ base_type=BASE_TYPES[0x02], # uint8 values={ 0: 'clear', # Allows clear of checksum for flash memory where can only write 1 to 0 without erasing sector. - 1: 'ok', # Set to mark checksum as valid if computes to invalid values 0 or 0xFF. Checksum can also be set to ok to save encoding computation time. + 1: 'ok', # Set to mark checksum as valid if computes to invalid values 0 or 0xFF. Checksum can also be set to ok to save encoding computation time. }, ), 'chop_exercise_name': FieldType( @@ -486,6 +663,15 @@ 22: 'standing_stability_reverse_chop', }, ), + 'climb_pro_event': FieldType( + name='climb_pro_event', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'approach', + 1: 'start', + 2: 'complete', + }, + ), 'comm_timeout_type': FieldType( name='comm_timeout_type', base_type=BASE_TYPES[0x84], # uint16 @@ -584,6 +770,54 @@ 43: 'overhead_walk', 44: 'inchworm', 45: 'weighted_modified_front_lever', + 46: 'russian_twist', + 47: 'abdominal_leg_rotations', # Deprecated do not use + 48: 'arm_and_leg_extension_on_knees', + 49: 'bicycle', + 50: 'bicep_curl_with_leg_extension', + 51: 'cat_cow', + 52: 'corkscrew', + 53: 'criss_cross', + 54: 'criss_cross_with_ball', # Deprecated do not use + 55: 'double_leg_stretch', + 56: 'knee_folds', + 57: 'lower_lift', + 58: 'neck_pull', + 59: 'pelvic_clocks', + 60: 'roll_over', + 61: 'roll_up', + 62: 'rolling', + 63: 'rowing_1', + 64: 'rowing_2', + 65: 'scissors', + 66: 'single_leg_circles', + 67: 'single_leg_stretch', + 68: 'snake_twist_1_and_2', # Deprecated do not use + 69: 'swan', + 70: 'swimming', + 71: 'teaser', + 72: 'the_hundred', + 73: 'bicep_curl_with_leg_extension_with_weights', + 75: 'hanging_l_sit', + 77: 'lower_lift_with_weights', + 79: 'ring_l_sit', + 80: 'rowing_1_with_weights', + 81: 'rowing_2_with_weights', + 82: 'scissors_with_weights', + 83: 'single_leg_stretch_with_weights', + 84: 'toes_to_elbows', + 85: 'weighted_criss_cross', + 86: 'weighted_double_leg_stretch', + 87: 'weighted_the_hundred', + 88: 'l_sit', + 89: 'turkish_get_up', + 90: 'weighted_ring_l_sit', + 91: 'weighted_hanging_l_sit', + 92: 'weighted_l_sit', + 93: 'side_bend_low_wheelchair', + 94: 'side_bend_mid_wheelchair', + 95: 'side_bend_high_wheelchair', + 96: 'seated_side_bend', }, ), 'course_capabilities': FieldType( @@ -601,6 +835,7 @@ 0x00000100: 'training', 0x00000200: 'navigation', 0x00000400: 'bikeway', + 0x00001000: 'aviation', # Denote course files to be used as flight plans }, ), 'course_point': FieldType( @@ -633,6 +868,33 @@ 23: 'u_turn', 24: 'segment_start', 25: 'segment_end', + 27: 'campsite', + 28: 'aid_station', + 29: 'rest_area', + 30: 'general_distance', # Used with UpAhead + 31: 'service', + 32: 'energy_gel', + 33: 'sports_drink', + 34: 'mile_marker', + 35: 'checkpoint', + 36: 'shelter', + 37: 'meeting_spot', + 38: 'overlook', + 39: 'toilet', + 40: 'shower', + 41: 'gear', + 42: 'sharp_curve', + 43: 'steep_incline', + 44: 'tunnel', + 45: 'bridge', + 46: 'obstacle', + 47: 'crossing', + 48: 'store', + 49: 'transition', + 50: 'navaid', + 51: 'transport', + 52: 'alert', + 53: 'info', }, ), 'crunch_exercise_name': FieldType( @@ -723,6 +985,8 @@ 81: 'toes_to_bar', 82: 'weighted_toes_to_bar', 83: 'crunch', + 84: 'straight_leg_crunch_with_ball', + 86: 'leg_climb_crunch', }, ), 'curl_exercise_name': FieldType( @@ -773,6 +1037,13 @@ 41: 'swiss_ball_ez_bar_preacher_curl', 42: 'twisting_standing_dumbbell_biceps_curl', 43: 'wide_grip_ez_bar_biceps_curl', + 44: 'one_arm_concentration_curl', + 45: 'standing_zottman_biceps_curl', + 46: 'dumbbell_biceps_curl', + 47: 'drag_curl_wheelchair', + 48: 'dumbbell_biceps_curl_wheelchair', + 49: 'bottle_curl', + 50: 'seated_bottle_curl', }, ), 'date_mode': FieldType( @@ -823,6 +1094,11 @@ 16: 'sumo_deadlift_high_pull', 17: 'trap_bar_deadlift', 18: 'wide_grip_barbell_deadlift', + 20: 'kettlebell_deadlift', + 21: 'kettlebell_sumo_deadlift', + 23: 'romanian_deadlift', + 24: 'single_leg_romanian_deadlift_circuit', + 25: 'straight_leg_deadlift', }, ), 'device_index': FieldType( @@ -930,8 +1206,54 @@ name='dive_alarm_type', base_type=BASE_TYPES[0x00], # enum values={ - 0: 'depth', - 1: 'time', + 0: 'depth', # Alarm when a certain depth is crossed + 1: 'time', # Alarm when a certain time has transpired + 2: 'speed', # Alarm when a certain ascent or descent rate is exceeded + }, + ), + 'dive_alert': FieldType( + name='dive_alert', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'ndl_reached', + 1: 'gas_switch_prompted', + 2: 'near_surface', + 3: 'approaching_ndl', + 4: 'po2_warn', + 5: 'po2_crit_high', + 6: 'po2_crit_low', + 7: 'time_alert', + 8: 'depth_alert', + 9: 'deco_ceiling_broken', + 10: 'deco_complete', + 11: 'safety_stop_broken', + 12: 'safety_stop_complete', + 13: 'cns_warning', + 14: 'cns_critical', + 15: 'otu_warning', + 16: 'otu_critical', + 17: 'ascent_critical', + 18: 'alert_dismissed_by_key', + 19: 'alert_dismissed_by_timeout', + 20: 'battery_low', + 21: 'battery_critical', + 22: 'safety_stop_started', + 23: 'approaching_first_deco_stop', + 24: 'setpoint_switch_auto_low', + 25: 'setpoint_switch_auto_high', + 26: 'setpoint_switch_manual_low', + 27: 'setpoint_switch_manual_high', + 28: 'auto_setpoint_switch_ignored', + 29: 'switched_to_open_circuit', + 30: 'switched_to_closed_circuit', + 32: 'tank_battery_low', + 33: 'po2_ccr_dil_low', # ccr diluent has low po2 + 34: 'deco_stop_cleared', # a deco stop has been cleared + 35: 'apnea_neutral_buoyancy', # Target Depth Apnea Alarm triggered + 36: 'apnea_target_depth', # Neutral Buoyance Apnea Alarm triggered + 37: 'apnea_surface', # Surface Apnea Alarm triggered + 38: 'apnea_high_speed', # High Speed Apnea Alarm triggered + 39: 'apnea_low_speed', # Low Speed Apnea Alarm triggered }, ), 'dive_backlight_mode': FieldType( @@ -942,6 +1264,14 @@ 1: 'always_on', }, ), + 'dive_gas_mode': FieldType( + name='dive_gas_mode', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'open_circuit', + 1: 'closed_circuit_diluent', + }, + ), 'dive_gas_status': FieldType( name='dive_gas_status', base_type=BASE_TYPES[0x00], # enum @@ -951,13 +1281,20 @@ 2: 'backup_only', }, ), + 'elliptical_exercise_name': FieldType( + name='elliptical_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'elliptical', + }, + ), 'event': FieldType( name='event', base_type=BASE_TYPES[0x00], # enum values={ - 0: 'timer', # Group 0. Start / stop_all + 0: 'timer', # Group 0. Start / stop_all 3: 'workout', # start / stop - 4: 'workout_step', # Start at beginning of workout. Stop at end of each step. + 4: 'workout_step', # Start at beginning of workout. Stop at end of each step. 5: 'power_down', # stop_all group 0 6: 'power_up', # stop_all group 0 7: 'off_course', # start / stop group 0 @@ -965,21 +1302,21 @@ 9: 'lap', # Stop at end of each lap. 10: 'course_point', # marker 11: 'battery', # marker - 12: 'virtual_partner_pace', # Group 1. Start at beginning of activity if VP enabled, when VP pace is changed during activity or VP enabled mid activity. stop_disable when VP disabled. - 13: 'hr_high_alert', # Group 0. Start / stop when in alert condition. - 14: 'hr_low_alert', # Group 0. Start / stop when in alert condition. - 15: 'speed_high_alert', # Group 0. Start / stop when in alert condition. - 16: 'speed_low_alert', # Group 0. Start / stop when in alert condition. - 17: 'cad_high_alert', # Group 0. Start / stop when in alert condition. - 18: 'cad_low_alert', # Group 0. Start / stop when in alert condition. - 19: 'power_high_alert', # Group 0. Start / stop when in alert condition. - 20: 'power_low_alert', # Group 0. Start / stop when in alert condition. + 12: 'virtual_partner_pace', # Group 1. Start at beginning of activity if VP enabled, when VP pace is changed during activity or VP enabled mid activity. stop_disable when VP disabled. + 13: 'hr_high_alert', # Group 0. Start / stop when in alert condition. + 14: 'hr_low_alert', # Group 0. Start / stop when in alert condition. + 15: 'speed_high_alert', # Group 0. Start / stop when in alert condition. + 16: 'speed_low_alert', # Group 0. Start / stop when in alert condition. + 17: 'cad_high_alert', # Group 0. Start / stop when in alert condition. + 18: 'cad_low_alert', # Group 0. Start / stop when in alert condition. + 19: 'power_high_alert', # Group 0. Start / stop when in alert condition. + 20: 'power_low_alert', # Group 0. Start / stop when in alert condition. 21: 'recovery_hr', # marker 22: 'battery_low', # marker - 23: 'time_duration_alert', # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled. - 24: 'distance_duration_alert', # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled. - 25: 'calorie_duration_alert', # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled. - 26: 'activity', # Group 1.. Stop at end of activity. + 23: 'time_duration_alert', # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled. + 24: 'distance_duration_alert', # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled. + 25: 'calorie_duration_alert', # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled. + 26: 'activity', # Group 1.. Stop at end of activity. 27: 'fitness_equipment', # marker 28: 'length', # Stop at end of each length. 32: 'user_marker', # marker @@ -988,9 +1325,19 @@ 42: 'front_gear_change', # marker 43: 'rear_gear_change', # marker 44: 'rider_position_change', # marker - 45: 'elev_high_alert', # Group 0. Start / stop when in alert condition. - 46: 'elev_low_alert', # Group 0. Start / stop when in alert condition. + 45: 'elev_high_alert', # Group 0. Start / stop when in alert condition. + 46: 'elev_low_alert', # Group 0. Start / stop when in alert condition. 47: 'comm_timeout', # marker + 54: 'auto_activity_detect', # marker + 56: 'dive_alert', # marker + 57: 'dive_gas_switched', # marker + 71: 'tank_pressure_reserve', # marker + 72: 'tank_pressure_critical', # marker + 73: 'tank_lost', # marker + 75: 'radar_threat_alert', # start/stop/marker + 76: 'tank_battery_low', # marker + 81: 'tank_pod_connected', # marker - tank pod has connected + 82: 'tank_pod_disconnected', # marker - tank pod has lost connection }, ), 'event_type': FieldType( @@ -1197,6 +1544,7 @@ 5: 'full_quarter_split', 6: 'half_vertical_left_split', 7: 'half_horizontal_top_split', + 8: 'dynamic', # The EXD may display the configured concepts in any layout it sees fit. }, ), 'exd_qualifiers': FieldType( @@ -1286,9 +1634,36 @@ 30: 'triceps_extension', 31: 'warm_up', 32: 'run', + 33: 'bike', + 34: 'cardio_sensors', # Exercises within workouts that use GPS/sensors rather than rep counting + 35: 'move', + 36: 'pose', + 37: 'banded_exercises', + 38: 'battle_rope', + 39: 'elliptical', + 40: 'floor_climb', + 41: 'indoor_bike', + 42: 'indoor_row', + 43: 'ladder', + 44: 'sandbag', + 45: 'sled', + 46: 'sledge_hammer', + 47: 'stair_stepper', + 49: 'suspension', + 50: 'tire', + 52: 'run_indoor', + 53: 'bike_outdoor', 65534: 'unknown', }, ), + 'favero_product': FieldType( + name='favero_product', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 10: 'assioma_uno', + 12: 'assioma_duo', + }, + ), 'file': FieldType( name='file', base_type=BASE_TYPES[0x00], # enum @@ -1308,8 +1683,8 @@ 20: 'activity_summary', # Read/erase, multiple files. Directory=Activities 28: 'monitoring_daily', 32: 'monitoring_b', # Read only. Directory=Monitoring. File number=identifier - 34: 'segment', # Read/write/erase. Multiple Files. Directory=Segments - 35: 'segment_list', # Read/write/erase. Single File. Directory=Segments + 34: 'segment', # Read/write/erase. Multiple Files. Directory=Segments + 35: 'segment_list', # Read/write/erase. Single File. Directory=Segments 40: 'exd_configuration', # Read/write/erase. Single File. Directory=Settings 0xF7: 'mfg_range_min', # 0xF7 - 0xFE reserved for manufacturer specific file types 0xFE: 'mfg_range_max', # 0xF7 - 0xFE reserved for manufacturer specific file types @@ -1366,6 +1741,13 @@ 3: 'unknown', # lost connection to fitness equipment }, ), + 'floor_climb_exercise_name': FieldType( + name='floor_climb_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'floor_climb', + }, + ), 'flye_exercise_name': FieldType( name='flye_exercise_name', base_type=BASE_TYPES[0x84], # uint16 @@ -1378,16 +1760,13 @@ 5: 'kneeling_rear_flye', 6: 'single_arm_standing_cable_reverse_flye', 7: 'swiss_ball_dumbbell_flye', + 8: 'arm_rotations', + 9: 'hug_a_tree', + 10: 'face_down_incline_reverse_flye', + 11: 'incline_reverse_flye', + 12: 'rear_delt_fly_wheelchair', }, ), - 'strava_product': FieldType( - name='strava_product', - base_type=BASE_TYPES[0x84], # uint16 - values={ - 101: 'Strava iPhone App', # recent versions of Strava iPhone app - 102: 'Strava Android App', # recent versions of Strava Android app - } - ), 'garmin_product': FieldType( name='garmin_product', base_type=BASE_TYPES[0x84], # uint16 @@ -1404,7 +1783,12 @@ 10: 'bcm', # BCM model for ANT+ messaging 11: 'axs01', # AXS01 HRM Bike Chipset model for ANT+ messaging 12: 'hrm_tri_single_byte_product_id', # hrm_tri model for HRM ANT+ messaging + 13: 'hrm4_run_single_byte_product_id', # hrm4 run model for HRM ANT+ messaging 14: 'fr225_single_byte_product_id', # fr225 model for HRM ANT+ messaging + 15: 'gen3_bsm_single_byte_product_id', # gen3_bsm model for Bike Speed ANT+ messaging + 16: 'gen3_bcm_single_byte_product_id', # gen3_bcm model for Bike Cadence ANT+ messaging + 22: 'hrm_fit_single_byte_product_id', + 255: 'OHR', # Garmin Wearable Optical Heart Rate Sensor for ANT+ HR Profile Broadcasting 473: 'fr301_china', 474: 'fr301_japan', 475: 'fr301_korea', @@ -1433,6 +1817,7 @@ 1381: 'vector_cp', 1386: 'edge800_china', 1387: 'edge500_china', + 1405: 'approach_g10', 1410: 'fr610_japan', 1422: 'edge500_korea', 1436: 'fr70', @@ -1456,7 +1841,7 @@ 1735: 'virb_elite', 1736: 'edge_touring', # Also Edge Touring Plus 1742: 'edge510_japan', - 1743: 'hrm_tri', + 1743: 'hrm_tri', # Also HRM-Swim 1752: 'hrm_run', 1765: 'fr920xt', 1821: 'edge510_asia', @@ -1499,6 +1884,7 @@ 2153: 'fr225', 2156: 'fr630', 2157: 'fr230', + 2158: 'fr735xt', 2160: 'vivo_active_apac', 2161: 'vector_2', 2162: 'vector_2s', @@ -1506,6 +1892,7 @@ 2173: 'fr620_taiwan', 2174: 'fr220_taiwan', 2175: 'truswing', + 2187: 'd2airvenu', 2188: 'fenix3_china', 2189: 'fenix3_twn', 2192: 'varia_headlight', @@ -1515,16 +1902,37 @@ 2225: 'varia_radar_taillight', 2226: 'varia_radar_display', 2238: 'edge20', + 2260: 'edge520_asia', + 2261: 'edge520_japan', 2262: 'd2_bravo', 2266: 'approach_s20', + 2271: 'vivo_smart2', + 2274: 'edge1000_thai', 2276: 'varia_remote', + 2288: 'edge25_asia', + 2289: 'edge25_jpn', + 2290: 'edge20_asia', + 2292: 'approach_x40', + 2293: 'fenix3_japan', + 2294: 'vivo_smart_emea', + 2310: 'fr630_asia', + 2311: 'fr630_jpn', + 2313: 'fr230_jpn', 2327: 'hrm4_run', + 2332: 'epix_japan', 2337: 'vivo_active_hr', 2347: 'vivo_smart_gps_hr', 2348: 'vivo_smart_hr', + 2361: 'vivo_smart_hr_asia', + 2362: 'vivo_smart_gps_hr_asia', 2368: 'vivo_move', + 2379: 'varia_taillight', + 2396: 'fr235_asia', + 2397: 'fr235_japan', 2398: 'varia_vision', 2406: 'vivo_fit3', + 2407: 'fenix3_korea', + 2408: 'fenix3_sea', 2413: 'fenix3_hr', 2417: 'virb_ultra_30', 2429: 'index_smart_scale', @@ -1532,25 +1940,310 @@ 2432: 'fenix3_chronos', 2441: 'oregon7xx', 2444: 'rino7xx', + 2457: 'epix_korea', + 2473: 'fenix3_hr_chn', + 2474: 'fenix3_hr_twn', + 2475: 'fenix3_hr_jpn', + 2476: 'fenix3_hr_sea', + 2477: 'fenix3_hr_kor', 2496: 'nautix', + 2497: 'vivo_active_hr_apac', + 2503: 'fr35', + 2512: 'oregon7xx_ww', 2530: 'edge_820', 2531: 'edge_explore_820', + 2533: 'fr735xt_apac', + 2534: 'fr735xt_japan', 2544: 'fenix5s', 2547: 'd2_bravo_titanium', 2567: 'varia_ut800', # Varia UT 800 SW 2593: 'running_dynamics_pod', + 2599: 'edge_820_china', + 2600: 'edge_820_japan', 2604: 'fenix5x', 2606: 'vivo_fit_jr', + 2622: 'vivo_smart3', + 2623: 'vivo_sport', + 2628: 'edge_820_taiwan', + 2629: 'edge_820_korea', + 2630: 'edge_820_sea', + 2650: 'fr35_hebrew', + 2656: 'approach_s60', + 2667: 'fr35_apac', + 2668: 'fr35_japan', + 2675: 'fenix3_chronos_asia', + 2687: 'virb_360', 2691: 'fr935', 2697: 'fenix5', + 2700: 'vivoactive3', + 2713: 'edge_1030', + 2727: 'fr35_sea', + 2733: 'fr235_china_nfc', + 2769: 'foretrex_601_701', + 2772: 'vivo_move_hr', + 2787: 'vector_3', + 2796: 'fenix5_asia', + 2797: 'fenix5s_asia', + 2798: 'fenix5x_asia', + 2806: 'approach_z80', + 2814: 'fr35_korea', + 2819: 'd2charlie', + 2831: 'vivo_smart3_apac', + 2832: 'vivo_sport_apac', + 2833: 'fr935_asia', + 2859: 'descent', + 2878: 'vivo_fit4', + 2886: 'fr645', + 2888: 'fr645m', + 2891: 'fr30', + 2900: 'fenix5s_plus', + 2909: 'Edge_130', + 2924: 'edge_1030_asia', + 2927: 'vivosmart_4', + 2945: 'vivo_move_hr_asia', + 2962: 'approach_x10', + 2977: 'fr30_asia', + 2988: 'vivoactive3m_w', + 3003: 'fr645_asia', + 3004: 'fr645m_asia', + 3011: 'edge_explore', + 3028: 'gpsmap66', + 3049: 'approach_s10', + 3066: 'vivoactive3m_l', + 3076: 'fr245', + 3077: 'fr245_music', + 3085: 'approach_g80', + 3092: 'edge_130_asia', + 3095: 'edge_1030_bontrager', + 3110: 'fenix5_plus', + 3111: 'fenix5x_plus', + 3112: 'edge_520_plus', + 3113: 'fr945', + 3121: 'edge_530', + 3122: 'edge_830', + 3126: 'instinct_esports', + 3134: 'fenix5s_plus_apac', + 3135: 'fenix5x_plus_apac', + 3142: 'edge_520_plus_apac', + 3143: 'descent_t1', + 3144: 'fr235l_asia', + 3145: 'fr245_asia', + 3163: 'vivo_active3m_apac', + 3192: 'gen3_bsm', # gen3 bike speed sensor + 3193: 'gen3_bcm', # gen3 bike cadence sensor + 3218: 'vivo_smart4_asia', + 3224: 'vivoactive4_small', + 3225: 'vivoactive4_large', + 3226: 'venu', + 3246: 'marq_driver', + 3247: 'marq_aviator', + 3248: 'marq_captain', + 3249: 'marq_commander', + 3250: 'marq_expedition', + 3251: 'marq_athlete', + 3258: 'descent_mk2', + 3282: 'fr45', + 3284: 'gpsmap66i', + 3287: 'fenix6S_sport', + 3288: 'fenix6S', + 3289: 'fenix6_sport', + 3290: 'fenix6', + 3291: 'fenix6x', + 3299: 'hrm_dual', # HRM-Dual + 3300: 'hrm_pro', # HRM-Pro + 3308: 'vivo_move3_premium', + 3314: 'approach_s40', + 3321: 'fr245m_asia', + 3349: 'edge_530_apac', + 3350: 'edge_830_apac', + 3378: 'vivo_move3', + 3387: 'vivo_active4_small_asia', + 3388: 'vivo_active4_large_asia', + 3389: 'vivo_active4_oled_asia', + 3405: 'swim2', + 3420: 'marq_driver_asia', + 3421: 'marq_aviator_asia', + 3422: 'vivo_move3_asia', + 3441: 'fr945_asia', + 3446: 'vivo_active3t_chn', + 3448: 'marq_captain_asia', + 3449: 'marq_commander_asia', + 3450: 'marq_expedition_asia', + 3451: 'marq_athlete_asia', + 3461: 'index_smart_scale_2', + 3466: 'instinct_solar', + 3469: 'fr45_asia', + 3473: 'vivoactive3_daimler', + 3498: 'legacy_rey', + 3499: 'legacy_darth_vader', + 3500: 'legacy_captain_marvel', + 3501: 'legacy_first_avenger', + 3512: 'fenix6s_sport_asia', + 3513: 'fenix6s_asia', + 3514: 'fenix6_sport_asia', + 3515: 'fenix6_asia', + 3516: 'fenix6x_asia', + 3535: 'legacy_captain_marvel_asia', + 3536: 'legacy_first_avenger_asia', + 3537: 'legacy_rey_asia', + 3538: 'legacy_darth_vader_asia', + 3542: 'descent_mk2s', + 3558: 'edge_130_plus', + 3570: 'edge_1030_plus', + 3578: 'rally_200', # Rally 100/200 Power Meter Series + 3589: 'fr745', + 3596: 'venusq_music', + 3599: 'venusq_music_v2', + 3600: 'venusq', + 3615: 'lily', + 3624: 'marq_adventurer', + 3638: 'enduro', + 3639: 'swim2_apac', + 3648: 'marq_adventurer_asia', + 3652: 'fr945_lte', + 3702: 'descent_mk2_asia', # Mk2 and Mk2i + 3703: 'venu2', + 3704: 'venu2s', + 3737: 'venu_daimler_asia', + 3739: 'marq_golfer', + 3740: 'venu_daimler', + 3794: 'fr745_asia', + 3808: 'varia_rct715', + 3809: 'lily_asia', + 3812: 'edge_1030_plus_asia', + 3813: 'edge_130_plus_asia', + 3823: 'approach_s12', + 3837: 'venusq_asia', + 3843: 'edge_1040', + 3850: 'marq_golfer_asia', + 3851: 'venu2_plus', + 3865: 'gnss', # Airoha AG3335M Family + 3869: 'fr55', + 3872: 'enduro_asia', + 3888: 'instinct_2', + 3889: 'instinct_2s', + 3905: 'fenix7s', + 3906: 'fenix7', + 3907: 'fenix7x', + 3908: 'fenix7s_apac', + 3909: 'fenix7_apac', + 3910: 'fenix7x_apac', + 3930: 'descent_mk2s_asia', + 3934: 'approach_s42', + 3943: 'epix_gen2', + 3944: 'epix_gen2_apac', + 3949: 'venu2s_asia', + 3950: 'venu2_asia', + 3978: 'fr945_lte_asia', + 3982: 'vivo_move_sport', + 3983: 'vivomove_trend', + 3986: 'approach_S12_asia', + 3990: 'fr255_music', + 3991: 'fr255_small_music', + 3992: 'fr255', + 3993: 'fr255_small', + 4002: 'approach_s42_asia', + 4005: 'descent_g1', + 4017: 'venu2_plus_asia', + 4024: 'fr955', + 4033: 'fr55_asia', + 4061: 'edge_540', + 4062: 'edge_840', + 4063: 'vivosmart_5', + 4071: 'instinct_2_asia', + 4105: 'marq_gen2', # Adventurer, Athlete, Captain, Golfer + 4115: 'venusq2', + 4116: 'venusq2music', + 4124: 'marq_gen2_aviator', + 4125: 'd2_air_x10', + 4130: 'hrm_pro_plus', + 4132: 'descent_g1_asia', + 4135: 'tactix7', + 4155: 'instinct_crossover', + 4169: 'edge_explore2', + 4222: 'descent_mk3', + 4223: 'descent_mk3i', + 4233: 'approach_s70', + 4257: 'fr265_large', + 4258: 'fr265_small', + 4260: 'venu3', + 4261: 'venu3s', + 4265: 'tacx_neo_smart', # Neo Smart, Tacx + 4266: 'tacx_neo2_smart', # Neo 2 Smart, Tacx + 4267: 'tacx_neo2_t_smart', # Neo 2T Smart, Tacx + 4268: 'tacx_neo_smart_bike', # Neo Smart Bike, Tacx + 4269: 'tacx_satori_smart', # Satori Smart, Tacx + 4270: 'tacx_flow_smart', # Flow Smart, Tacx + 4271: 'tacx_vortex_smart', # Vortex Smart, Tacx + 4272: 'tacx_bushido_smart', # Bushido Smart, Tacx + 4273: 'tacx_genius_smart', # Genius Smart, Tacx + 4274: 'tacx_flux_flux_s_smart', # Flux/Flux S Smart, Tacx + 4275: 'tacx_flux2_smart', # Flux 2 Smart, Tacx + 4276: 'tacx_magnum', # Magnum, Tacx + 4305: 'edge_1040_asia', + 4312: 'epix_gen2_pro_42', + 4313: 'epix_gen2_pro_47', + 4314: 'epix_gen2_pro_51', + 4315: 'fr965', + 4341: 'enduro2', + 4374: 'fenix7s_pro_solar', + 4375: 'fenix7_pro_solar', + 4376: 'fenix7x_pro_solar', + 4380: 'lily2', + 4394: 'instinct_2x', + 4426: 'vivoactive5', + 4432: 'fr165', + 4433: 'fr165_music', + 4440: 'edge_1050', + 4442: 'descent_t2', + 4446: 'hrm_fit', + 4472: 'marq_gen2_commander', + 4477: 'lily_athlete', # aka the Lily 2 Active + 4532: 'fenix8_solar', + 4533: 'fenix8_solar_large', + 4534: 'fenix8_small', + 4536: 'fenix8', + 4556: 'd2_mach1_pro', + 4575: 'enduro3', + 4583: 'instinctE_40mm', + 4584: 'instinctE_45mm', + 4585: 'instinct3_solar_45mm', + 4586: 'instinct3_amoled_45mm', + 4587: 'instinct3_amoled_50mm', + 4588: 'descent_g2', + 4606: 'hrm_200', + 4625: 'vivoactive6', + 4647: 'approachS44', + 4656: 'approachS50', + 4666: 'fenix_e', + 4759: 'instinct3_solar_50mm', + 4775: 'tactix8_amoled', + 4776: 'tactix8_solar', 10007: 'sdm4', # SDM4 footpod 10014: 'edge_remote', + 3927: 'approach_g12', + 4001: 'approach_g12_asia', 20119: 'training_center', + 20533: 'tacx_training_app_win', + 20534: 'tacx_training_app_mac', + 20565: 'tacx_training_app_mac_catalyst', + 30045: 'tacx_training_app_android', + 30046: 'tacx_training_app_ios', + 30047: 'tacx_training_app_legacy', 65531: 'connectiq_simulator', 65532: 'android_antplus_plugin', 65534: 'connect', # Garmin Connect website }, ), + 'gas_consumption_rate_type': FieldType( + name='gas_consumption_rate_type', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'pressure_sac', # Pressure-based Surface Air Consumption + 1: 'volume_sac', # Volumetric Surface Air Consumption + 2: 'rmv', # Respiratory Minute Volume + }, + ), 'gender': FieldType( name='gender', base_type=BASE_TYPES[0x00], # enum @@ -1640,6 +2333,13 @@ 40: 'single_leg_hip_raise_with_head_on_bosu_ball', 41: 'weighted_single_leg_hip_raise_with_head_on_bosu_ball', 42: 'weighted_clam_bridge', + 43: 'single_leg_swiss_ball_hip_raise_and_leg_curl', + 44: 'clams', + 45: 'inner_thigh_circles', # Deprecated do not use + 46: 'inner_thigh_side_lift', # Deprecated do not use + 47: 'leg_circles', + 48: 'leg_lift', + 49: 'leg_lift_in_external_rotation', }, ), 'hip_stability_exercise_name': FieldType( @@ -1680,6 +2380,7 @@ 31: 'weighted_standing_rear_leg_raise', 32: 'supine_hip_internal_rotation', 33: 'weighted_supine_hip_internal_rotation', + 34: 'lying_abduction_stretch', }, ), 'hip_swing_exercise_name': FieldType( @@ -1689,6 +2390,7 @@ 0: 'single_arm_kettlebell_swing', 1: 'single_arm_dumbbell_swing', 2: 'step_out_swing', + 3: 'one_arm_swing', }, ), 'hr_type': FieldType( @@ -1706,6 +2408,18 @@ 0: 'custom', 1: 'percent_max_hr', 2: 'percent_hrr', + 3: 'percent_lthr', + }, + ), + 'hrv_status': FieldType( + name='hrv_status', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'none', + 1: 'poor', + 2: 'low', + 3: 'unbalanced', + 4: 'balanced', }, ), 'hyperextension_exercise_name': FieldType( @@ -1749,6 +2463,25 @@ 34: 'weighted_swiss_ball_hyperextension', 35: 'swiss_ball_opposite_arm_and_leg_lift', 36: 'weighted_swiss_ball_opposite_arm_and_leg_lift', + 37: 'superman_on_swiss_ball', + 38: 'cobra', + 39: 'supine_floor_barre', # Deprecated do not use + }, + ), + 'indoor_bike_exercise_name': FieldType( + name='indoor_bike_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'air_bike', + 1: 'assault_bike', + 3: 'stationary_bike', + }, + ), + 'indoor_row_exercise_name': FieldType( + name='indoor_row_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'rowing_machine', }, ), 'intensity': FieldType( @@ -1759,6 +2492,17 @@ 1: 'rest', 2: 'warmup', 3: 'cooldown', + 4: 'recovery', + 5: 'interval', + 6: 'other', + }, + ), + 'ladder_exercise_name': FieldType( + name='ladder_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'agility', + 1: 'speed', }, ), 'language': FieldType( @@ -1925,6 +2669,15 @@ 29: 'underhand_grip_rear_lateral_raise', 30: 'wall_slide', 31: 'weighted_wall_slide', + 32: 'arm_circles', + 33: 'shaving_the_head', + 34: 'dumbbell_lateral_raise', + 36: 'ring_dip_kipping', + 37: 'wall_walk', + 38: 'dumbbell_front_raise_wheelchair', + 39: 'dumbbell_lateral_raise_wheelchair', + 40: 'pole_double_arm_overhead_and_forward_wheelchair', + 41: 'pole_straight_arm_overhead_wheelchair', }, ), 'left_right_balance': FieldType( @@ -1959,6 +2712,8 @@ 9: 'staggered_stance_good_morning', 10: 'swiss_ball_hip_raise_and_leg_curl', 11: 'zercher_good_morning', + 12: 'band_good_morning', + 13: 'bar_good_morning', }, ), 'leg_raise_exercise_name': FieldType( @@ -2007,6 +2762,16 @@ 'local_device_type': FieldType( name='local_device_type', base_type=BASE_TYPES[0x02], # uint8 + values={ + 0: 'gps', # Onboard gps receiver + 1: 'glonass', # Onboard glonass receiver + 2: 'gps_glonass', # Onboard gps glonass receiver + 3: 'accelerometer', # Onboard sensor + 4: 'barometer', # Onboard sensor + 5: 'temperature', # Onboard sensor + 10: 'whr', # Onboard wrist HR sensor + 12: 'sensor_hub', # Onboard software package + }, ), 'localtime_into_day': FieldType( # number of seconds into the day since local 00:00:00 name='localtime_into_day', @@ -2097,6 +2862,16 @@ 78: 'walking_lunge', 79: 'weighted_walking_lunge', 80: 'wide_grip_overhead_barbell_split_squat', + 81: 'alternating_dumbbell_lunge', + 82: 'dumbbell_reverse_lunge', + 83: 'overhead_dumbbell_lunge', + 84: 'scissor_power_switch', + 85: 'dumbbell_overhead_walking_lunge', + 86: 'curtsy_lunge', + 87: 'weighted_curtsy_lunge', + 88: 'weighted_shifting_side_lunge', + 89: 'weighted_side_lunge_and_press', + 90: 'weighted_side_lunge_jump_off', }, ), 'manufacturer': FieldType( @@ -2104,7 +2879,7 @@ base_type=BASE_TYPES[0x84], # uint16 values={ 1: 'garmin', - 2: 'garmin_fr405_antfs', # Do not use. Used by FR405 for ANTFS man id. + 2: 'garmin_fr405_antfs', # Do not use. Used by FR405 for ANTFS man id. 3: 'zephyr', 4: 'dayton', 5: 'idt', @@ -2143,6 +2918,7 @@ 38: 'osynce', 39: 'holux', 40: 'concept2', + 41: 'shimano', 42: 'one_giant_leap', 43: 'ace_sensor', 44: 'brim_brothers', @@ -2224,6 +3000,35 @@ 122: 'johnson_health_tech', 123: 'polar_electro', 124: 'seesense', + 125: 'nci_technology', + 126: 'iqsquare', + 127: 'leomo', + 128: 'ifit_com', + 129: 'coros_byte', + 130: 'versa_design', + 131: 'chileaf', + 132: 'cycplus', + 133: 'gravaa_byte', + 134: 'sigeyi', + 135: 'coospo', + 136: 'geoid', + 137: 'bosch', + 138: 'kyto', + 139: 'kinetic_sports', + 140: 'decathlon_byte', + 141: 'tq_systems', + 142: 'tag_heuer', + 143: 'keiser_fitness', + 144: 'zwift_byte', + 145: 'porsche_ep', + 146: 'blackbird', + 147: 'meilan_byte', + 148: 'ezon', + 149: 'laisi', + 150: 'myzone', + 151: 'abawo', + 152: 'bafang', + 153: 'luhong_technology', 255: 'development', 257: 'healthandlife', 258: 'lezyne', @@ -2262,9 +3067,76 @@ 291: 'shapelog', 292: 'dabuziduo', 293: 'jetblack', + 294: 'coros', + 295: 'virtugo', + 296: 'velosense', + 297: 'cycligentinc', + 298: 'trailforks', + 299: 'mahle_ebikemotion', + 300: 'nurvv', + 301: 'microprogram', + 302: 'zone5cloud', + 303: 'greenteg', + 304: 'yamaha_motors', + 305: 'whoop', + 306: 'gravaa', + 307: 'onelap', + 308: 'monark_exercise', + 309: 'form', + 310: 'decathlon', + 311: 'syncros', + 312: 'heatup', + 313: 'cannondale', + 314: 'true_fitness', + 315: 'RGT_cycling', + 316: 'vasa', + 317: 'race_republic', + 318: 'fazua', + 319: 'oreka_training', + 320: 'lsec', # Lishun Electric & Communication + 321: 'lululemon_studio', + 322: 'shanyue', + 323: 'spinning_mda', + 324: 'hilldating', + 325: 'aero_sensor', + 326: 'nike', + 327: 'magicshine', + 328: 'ictrainer', + 329: 'absolute_cycling', + 330: 'eo_swimbetter', + 331: 'mywhoosh', + 332: 'ravemen', + 333: 'tektro_racing_products', + 334: 'darad_innovation_corporation', + 335: 'cycloptim', 5759: 'actigraphcorp', }, ), + 'max_met_category': FieldType( + name='max_met_category', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'generic', + 1: 'cycling', + }, + ), + 'max_met_heart_rate_source': FieldType( + name='max_met_heart_rate_source', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'whr', # Wrist Heart Rate Monitor + 1: 'hrm', # Chest Strap Heart Rate Monitor + }, + ), + 'max_met_speed_source': FieldType( + name='max_met_speed_source', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'onboard_gps', + 1: 'connected_gps', + 2: 'cadence', + }, + ), 'mesg_count': FieldType( name='mesg_count', base_type=BASE_TYPES[0x00], # enum @@ -2290,6 +3162,7 @@ 9: 'power_zone', 10: 'met_zone', 12: 'sport', + 13: 'training_settings', 15: 'goal', 18: 'session', 19: 'lap', @@ -2357,13 +3230,47 @@ 208: 'magnetometer_data', 209: 'barometer_data', 210: 'one_d_sensor_calibration', + 211: 'monitoring_hr_data', + 216: 'time_in_zone', 225: 'set', 227: 'stress_level', + 229: 'max_met_data', 258: 'dive_settings', 259: 'dive_gas', 262: 'dive_alarm', 264: 'exercise_title', 268: 'dive_summary', + 269: 'spo2_data', + 275: 'sleep_level', + 285: 'jump', + 289: 'aad_accel_features', + 290: 'beat_intervals', + 297: 'respiration_rate', + 302: 'hsa_accelerometer_data', + 304: 'hsa_step_data', + 305: 'hsa_spo2_data', + 306: 'hsa_stress_data', + 307: 'hsa_respiration_data', + 308: 'hsa_heart_rate_data', + 312: 'split', + 313: 'split_summary', + 314: 'hsa_body_battery_data', + 315: 'hsa_event', + 317: 'climb_pro', + 319: 'tank_update', + 323: 'tank_summary', + 346: 'sleep_assessment', + 370: 'hrv_status_summary', + 371: 'hrv_value', + 372: 'raw_bbi', + 375: 'device_aux_battery_info', + 376: 'hsa_gyroscope_data', + 387: 'chrono_shot_session', + 388: 'chrono_shot_data', + 389: 'hsa_configuration_data', + 393: 'dive_apnea_alarm', + 398: 'skin_temp_overnight', + 409: 'hsa_wrist_temperature_data', # Message number for the HSA wrist temperature data message }, ), 'message_index': FieldType( @@ -2375,6 +3282,105 @@ 0x8000: 'selected', # message is selected if set }, ), + 'move_exercise_name': FieldType( + name='move_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'arch_and_curl', + 1: 'arm_circles_with_ball_band_and_weight', + 2: 'arm_stretch', + 3: 'back_massage', + 4: 'belly_breathing', + 5: 'bridge_with_ball', + 6: 'diamond_leg_crunch', + 7: 'diamond_leg_lift', + 8: 'eight_point_shoulder_opener', + 9: 'foot_rolling', + 10: 'footwork', + 11: 'footwork_on_disc', + 12: 'forward_fold', + 13: 'frog_with_band', + 14: 'half_roll_up', + 15: 'hamstring_curl', + 16: 'hamstring_stretch', + 17: 'hip_stretch', + 18: 'hug_a_tree_with_ball_band_and_weight', + 19: 'knee_circles', + 20: 'knee_folds_on_disc', + 21: 'lateral_flexion', + 22: 'leg_stretch_with_band', + 23: 'leg_stretch_with_leg_circles', + 24: 'lower_lift_on_disc', + 25: 'lunge_squat', + 26: 'lunges_with_knee_lift', + 27: 'mermaid_stretch', + 28: 'neutral_pelvic_position', + 29: 'pelvic_clocks_on_disc', + 30: 'pilates_plie_squats_parallel_turned_out_flat_and_heels_with_chair', + 31: 'piriformis_stretch', + 32: 'plank_knee_crosses', + 33: 'plank_knee_pulls', + 34: 'plank_up_downs', + 35: 'prayer_mudra', + 36: 'psoas_lunge_stretch', + 37: 'ribcage_breathing', + 38: 'roll_down', + 39: 'roll_up_with_weight_and_band', + 40: 'saw', + 41: 'scapular_stabilization', + 42: 'scissors_on_disc', + 43: 'seated_hip_stretchup', + 44: 'seated_twist', + 45: 'shaving_the_head_with_ball_band_and_weight', + 46: 'spinal_twist', + 47: 'spinal_twist_stretch', + 48: 'spine_stretch_forward', + 49: 'squat_open_arm_twist_pose', + 50: 'squats_with_ball', + 51: 'stand_and_hang', + 52: 'standing_side_stretch', + 53: 'standing_single_leg_forward_bend_with_it_band_opener', + 54: 'straight_leg_crunch_with_leg_lift', + 55: 'straight_leg_crunch_with_leg_lift_with_ball', + 56: 'straight_leg_crunch_with_legs_crossed', + 57: 'straight_leg_crunch_with_legs_crossed_with_ball', + 58: 'straight_leg_diagonal_crunch', + 59: 'straight_leg_diagonal_crunch_with_ball', + 60: 'tailbone_curl', + 61: 'throat_lock', + 62: 'tick_tock_side_roll', + 63: 'twist', + 64: 'v_leg_crunches', + 65: 'v_sit', + 66: 'forward_fold_wheelchair', + 67: 'forward_fold_plus_wheelchair', + 68: 'arm_circles_low_forward_wheelchair', + 69: 'arm_circles_mid_forward_wheelchair', + 70: 'arm_circles_high_forward_wheelchair', + 71: 'arm_circles_low_backward_wheelchair', + 72: 'arm_circles_mid_backward_wheelchair', + 73: 'arm_circles_high_backward_wheelchair', + 74: 'core_twists_wheelchair', + 75: 'arm_raise_wheelchair', + 76: 'chest_expand_wheelchair', + 77: 'arm_extend_wheelchair', + 78: 'forward_bend_wheelchair', + 79: 'toe_touch_wheelchair', + 80: 'extended_toe_touch_wheelchair', + 81: 'seated_arm_circles', + 82: 'trunk_rotations', + 83: 'seated_trunk_rotations', + 84: 'toe_touch', + }, + ), + 'no_fly_time_mode': FieldType( + name='no_fly_time_mode', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'standard', # Standard Diver Alert Network no-fly guidance + 1: 'flat_24_hours', # Flat 24 hour no-fly guidance + }, + ), 'olympic_lift_exercise_name': FieldType( name='olympic_lift_exercise_name', base_type=BASE_TYPES[0x84], # uint16 @@ -2400,6 +3406,14 @@ 18: 'single_arm_kettlebell_snatch', 19: 'split_jerk', 20: 'squat_clean_and_jerk', + 21: 'dumbbell_hang_snatch', + 22: 'dumbbell_power_clean_and_jerk', + 23: 'dumbbell_power_clean_and_push_press', + 24: 'dumbbell_power_clean_and_strict_press', + 25: 'dumbbell_snatch', + 26: 'medicine_ball_clean', + 27: 'clean_and_press', + 28: 'snatch', }, ), 'plank_exercise_name': FieldType( @@ -2534,6 +3548,14 @@ 125: 'weighted_mountain_climber_with_hands_on_bench', 126: 'weighted_swiss_ball_plank_leg_lift_and_hold', 127: 'weighted_wide_stance_plank_with_opposite_arm_and_leg_lift', + 128: 'plank_with_feet_on_swiss_ball', + 129: 'side_plank_to_plank_with_reach_under', + 130: 'bridge_with_glute_lower_lift', + 131: 'bridge_one_leg_bridge', + 132: 'plank_with_arm_variations', + 133: 'plank_with_leg_lift', + 134: 'reverse_plank_with_leg_pull', + 135: 'ring_plank_sprawls', }, ), 'plyo_exercise_name': FieldType( @@ -2573,6 +3595,133 @@ 30: 'weighted_squat_jump_onto_box', 31: 'squat_jumps_in_and_out', 32: 'weighted_squat_jumps_in_and_out', + 33: 'box_jump', + 34: 'box_jump_overs', + 35: 'box_jump_overs_over_the_box', + 36: 'star_jump_squats', + 37: 'jump_squat', + }, + ), + 'pose_exercise_name': FieldType( + name='pose_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'all_fours', + 1: 'ankle_to_knee', + 2: 'baby_cobra', + 3: 'boat', + 4: 'bound_angle', + 5: 'bound_seated_single_leg_forward_bend', + 6: 'bow', + 7: 'bowed_half_moon', + 8: 'bridge', + 9: 'cat', + 10: 'chair', + 11: 'childs', + 12: 'corpse', + 13: 'cow_face', + 14: 'cow', + 15: 'devotional_warrior', + 16: 'dolphin_plank', + 17: 'dolphin', + 18: 'down_dog_knee_to_nose', + 19: 'down_dog_split', + 20: 'down_dog_split_open_hip_bent_knee', + 21: 'downward_facing_dog', + 22: 'eagle', + 23: 'easy_seated', + 24: 'extended_puppy', + 25: 'extended_side_angle', + 26: 'fish', + 27: 'four_limbed_staff', + 28: 'full_split', + 29: 'gate', + 30: 'half_chair_half_ankle_to_knee', + 31: 'half_moon', + 32: 'head_to_knee', + 33: 'heron', + 34: 'heros', + 35: 'high_lunge', + 36: 'knees_chest_chin', + 37: 'lizard', + 38: 'locust', + 39: 'low_lunge', + 40: 'low_lunge_twist', + 41: 'low_lunge_with_knee_down', + 42: 'mermaid', + 43: 'mountain', + 44: 'one_legged_downward_facing_pose_open_hip_bent_knee', + 45: 'one_legged_pigeon', + 46: 'peaceful_warrior', + 47: 'plank', + 48: 'plow', + 49: 'reclined_hand_to_foot', + 50: 'revolved_half_moon', + 51: 'revolved_head_to_knee', + 52: 'revolved_triangle', + 53: 'runners_lunge', + 54: 'seated_easy_side_bend', + 55: 'seated_easy_twist', + 56: 'seated_long_leg_forward_bend', + 57: 'seated_wide_leg_forward_bend', + 58: 'shoulder_stand', + 59: 'side_boat', + 60: 'side_plank', + 61: 'sphinx', + 62: 'squat_open_arm_twist', + 63: 'squat_palm_press', + 64: 'staff', + 65: 'standing_arms_up', + 66: 'standing_forward_bend_halfway_up', + 67: 'standing_forward_bend', + 68: 'standing_side_opener', + 69: 'standing_single_leg_forward_bend', + 70: 'standing_split', + 71: 'standing_wide_leg_forward_bend', + 72: 'standing_wide_leg_forward_bend_with_twist', + 73: 'supine_spinal_twist', + 74: 'table_top', + 75: 'thread_the_needle', + 76: 'thunderbolt', + 77: 'thunderbolt_pose_both_sides_arm_stretch', + 78: 'tree', + 79: 'triangle', + 80: 'up_dog', + 81: 'upward_facing_plank', + 82: 'warrior_one', + 83: 'warrior_three', + 84: 'warrior_two', + 85: 'wheel', + 86: 'wide_side_lunge', + 87: 'deep_breathing_wheelchair', + 88: 'deep_breathing_low_wheelchair', + 89: 'deep_breathing_mid_wheelchair', + 90: 'deep_breathing_high_wheelchair', + 91: 'prayer_wheelchair', + 92: 'overhead_prayer_wheelchair', + 93: 'cactus_wheelchair', + 94: 'breathing_punches_wheelchair', + 95: 'breathing_punches_extended_wheelchair', + 96: 'breathing_punches_overhead_wheelchair', + 97: 'breathing_punches_overhead_and_down_wheelchair', + 98: 'breathing_punches_side_wheelchair', + 99: 'breathing_punches_extended_side_wheelchair', + 100: 'breathing_punches_overhead_side_wheelchair', + 101: 'breathing_punches_overhead_and_down_side_wheelchair', + 102: 'left_hand_back_wheelchair', + 103: 'triangle_wheelchair', + 104: 'thread_the_needle_wheelchair', + 105: 'neck_flexion_and_extension_wheelchair', + 106: 'neck_lateral_flexion_wheelchair', + 107: 'spine_flexion_and_extension_wheelchair', + 108: 'spine_rotation_wheelchair', + 109: 'spine_lateral_flexion_wheelchair', + 110: 'alternative_skiing_wheelchair', + 111: 'reach_forward_wheelchair', + 112: 'warrior_wheelchair', + 113: 'reverse_warrior_wheelchair', + 114: 'downward_facing_dog_to_cobra', + 115: 'seated_cat_cow', }, ), 'power_phase_type': FieldType( @@ -2585,6 +3734,18 @@ 3: 'power_phase_center', }, ), + 'projectile_type': FieldType( + name='projectile_type', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'arrow', # Arrow projectile type + 1: 'rifle_cartridge', # Rifle cartridge projectile type + 2: 'pistol_cartridge', # Pistol cartridge projectile type + 3: 'shotshell', # Shotshell projectile type + 4: 'air_rifle_pellet', # Air rifle pellet projectile type + 5: 'other', # Other projectile type + }, + ), 'pull_up_exercise_name': FieldType( name='pull_up_exercise_name', base_type=BASE_TYPES[0x84], # uint16 @@ -2628,6 +3789,13 @@ 36: 'suspended_chin_up', 37: 'weighted_suspended_chin_up', 38: 'pull_up', + 39: 'chin_up', + 40: 'neutral_grip_chin_up', + 41: 'weighted_chin_up', + 42: 'band_assisted_pull_up', + 43: 'neutral_grip_pull_up', + 44: 'weighted_neutral_grip_chin_up', + 45: 'weighted_neutral_grip_pull_up', }, ), 'push_up_exercise_name': FieldType( @@ -2712,6 +3880,19 @@ 75: 'ring_push_up', 76: 'weighted_ring_push_up', 77: 'push_up', + 78: 'pilates_pushup', + 79: 'dynamic_push_up', + 80: 'kipping_handstand_push_up', + 81: 'shoulder_tapping_push_up', + 82: 'biceps_push_up', + 83: 'hindu_push_up', + 84: 'pike_push_up', + 85: 'wide_grip_push_up', + 86: 'weighted_biceps_push_up', + 87: 'weighted_hindu_push_up', + 88: 'weighted_pike_push_up', + 89: 'kipping_parallette_handstand_push_up', + 90: 'wall_push_up', }, ), 'pwr_zone_calc': FieldType( @@ -2722,6 +3903,16 @@ 1: 'percent_ftp', }, ), + 'radar_threat_level_type': FieldType( + name='radar_threat_level_type', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'threat_unknown', + 1: 'threat_none', + 2: 'threat_approaching', + 3: 'threat_approaching_fast', + }, + ), 'rider_position_type': FieldType( name='rider_position_type', base_type=BASE_TYPES[0x00], # enum @@ -2770,6 +3961,25 @@ 31: 'underhand_grip_cable_row', 32: 'v_grip_cable_row', 33: 'wide_grip_seated_cable_row', + 34: 'alternating_dumbbell_row', + 35: 'inverted_row', + 36: 'row', + 37: 'weighted_row', + 38: 'indoor_row', + 39: 'banded_face_pulls', + 40: 'chest_supported_dumbbell_row', + 41: 'decline_ring_row', + 42: 'elevated_ring_row', + 43: 'rdl_bent_over_row_with_barbell_dumbbell', + 44: 'ring_row', + 45: 'barbell_row', + 46: 'bent_over_row_with_barbell', + 47: 'bent_over_row_with_dumbell', + 48: 'seated_underhand_grip_cable_row', + 49: 'trx_inverted_row', + 50: 'weighted_inverted_row', + 51: 'weighted_trx_inverted_row', + 52: 'dumbbell_row_wheelchair', }, ), 'run_exercise_name': FieldType( @@ -2780,6 +3990,43 @@ 1: 'walk', 2: 'jog', 3: 'sprint', + 4: 'run_or_walk', + 5: 'speed_walk', + 6: 'warm_up', + }, + ), + 'run_indoor_exercise_name': FieldType( + name='run_indoor_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'indoor_track_run', + 1: 'treadmill', + }, + ), + 'sandbag_exercise_name': FieldType( + name='sandbag_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'around_the_world', + 1: 'back_squat', + 2: 'bear_crawl_pull_through', + 3: 'bear_hug_squat', + 4: 'clean', + 5: 'clean_and_press', + 6: 'curl', + 7: 'front_carry', + 8: 'front_squat', + 9: 'lunge', + 10: 'overhead_press', + 11: 'plank_pull_through', + 12: 'rotational_lunge', + 13: 'row', + 14: 'russian_twist', + 15: 'shouldering', + 16: 'shoveling', + 17: 'side_lunge', + 18: 'sprint', + 19: 'zercher_squat', }, ), 'schedule': FieldType( @@ -2820,8 +4067,12 @@ 6: 'qom', 7: 'pr', 8: 'goal', - 9: 'rival', + 9: 'carrot', 10: 'club_leader', + 11: 'rival', + 12: 'last', + 13: 'recent_best', + 14: 'course_record', }, ), 'segment_selection_type': FieldType( @@ -2888,6 +4139,13 @@ 21: 'split_stance_hammer_curl_to_press', 22: 'swiss_ball_dumbbell_shoulder_press', 23: 'weight_plate_front_raise', + 24: 'dumbbell_shoulder_press', + 25: 'military_press', + 27: 'strict_press', + 28: 'dumbbell_front_raise', + 29: 'dumbbell_curl_to_overhead_press_wheelchair', + 30: 'arnold_press_wheelchair', + 31: 'overhead_dumbbell_press_wheelchair', }, ), 'shoulder_stability_exercise_name': FieldType( @@ -2927,6 +4185,9 @@ 30: 'weighted_swiss_ball_w_raise', 31: 'swiss_ball_y_raise', 32: 'weighted_swiss_ball_y_raise', + 33: 'cable_internal_rotation', + 34: 'lying_internal_rotation', + 35: 'seated_dumbbell_internal_rotation', }, ), 'shrug_exercise_name': FieldType( @@ -2950,6 +4211,14 @@ 14: 'serratus_shrug', 15: 'weighted_serratus_shrug', 16: 'wide_grip_jump_shrug', + 17: 'wide_grip_barbell_shrug', + 18: 'behind_the_back_shrug', + 19: 'dumbbell_shrug_wheelchair', + 20: 'shrug_wheelchair', + 21: 'shrug_arm_down_wheelchair', + 22: 'shrug_arm_mid_wheelchair', + 23: 'shrug_arm_up_wheelchair', + 24: 'upright_row', }, ), 'side': FieldType( @@ -3002,6 +4271,40 @@ 35: 'x_abs', 36: 'weighted_x_abs', 37: 'sit_up', + 38: 'ghd_sit_ups', + 39: 'sit_up_turkish_get_up', + 40: 'russian_twist_on_swiss_ball', + }, + ), + 'sled_exercise_name': FieldType( + name='sled_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'backward_drag', + 1: 'chest_press', + 2: 'forward_drag', + 3: 'low_push', + 4: 'push', + 5: 'row', + }, + ), + 'sledge_hammer_exercise_name': FieldType( + name='sledge_hammer_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'lateral_swing', + 1: 'hammer_slam', + }, + ), + 'sleep_level': FieldType( + name='sleep_level', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'unmeasurable', + 1: 'awake', + 2: 'light', + 3: 'deep', + 4: 'rem', }, ), 'source_type': FieldType( @@ -3016,6 +4319,43 @@ 5: 'local', # Onboard device }, ), + 'split_type': FieldType( + name='split_type', + base_type=BASE_TYPES[0x00], # enum + values={ + 1: 'ascent_split', + 2: 'descent_split', + 3: 'interval_active', + 4: 'interval_rest', + 5: 'interval_warmup', + 6: 'interval_cooldown', + 7: 'interval_recovery', + 8: 'interval_other', + 9: 'climb_active', + 10: 'climb_rest', + 11: 'surf_active', + 12: 'run_active', + 13: 'run_rest', + 14: 'workout_round', + 17: 'rwd_run', # run/walk detection running + 18: 'rwd_walk', # run/walk detection walking + 21: 'windsurf_active', + 22: 'rwd_stand', # run/walk detection standing + 23: 'transition', # Marks the time going from ascent_split to descent_split/used in backcountry ski + 28: 'ski_lift_split', + 29: 'ski_run_split', + }, + ), + 'spo2_measurement_type': FieldType( + name='spo2_measurement_type', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'off_wrist', + 1: 'spot_check', + 2: 'continuous_check', + 3: 'periodic', + }, + ), 'sport': FieldType( name='sport', base_type=BASE_TYPES[0x00], # enum @@ -3069,6 +4409,25 @@ 46: 'jumpmaster', 47: 'boxing', 48: 'floor_climbing', + 49: 'baseball', + 53: 'diving', + 62: 'hiit', + 64: 'racket', + 65: 'wheelchair_push_walk', + 66: 'wheelchair_push_run', + 67: 'meditation', + 69: 'disc_golf', + 71: 'cricket', + 72: 'rugby', + 73: 'hockey', + 74: 'lacrosse', + 75: 'volleyball', + 76: 'water_tubing', + 77: 'wakesurfing', + 80: 'mixed_martial_arts', + 82: 'snorkeling', + 83: 'dance', + 84: 'jump_rope', 254: 'all', # All is for goals only to include all sports. }, ), @@ -3269,6 +4628,27 @@ 84: 'wide_stance_barbell_squat', 85: 'wide_stance_goblet_squat', 86: 'zercher_squat', + 87: 'kbs_overhead', # Deprecated do not use + 88: 'squat_and_side_kick', + 89: 'squat_jumps_in_n_out', + 90: 'pilates_plie_squats_parallel_turned_out_flat_and_heels', + 91: 'releve_straight_leg_and_knee_bent_with_one_leg_variation', + 92: 'alternating_box_dumbbell_step_ups', + 93: 'dumbbell_overhead_squat_single_arm', + 94: 'dumbbell_squat_snatch', + 95: 'medicine_ball_squat', + 97: 'wall_ball_squat_and_press', + 98: 'squat_american_swing', + 100: 'air_squat', + 101: 'dumbbell_thrusters', + 102: 'overhead_barbell_squat', + }, + ), + 'stair_stepper_exercise_name': FieldType( + name='stair_stepper_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'stair_stepper', }, ), 'stroke_type': FieldType( @@ -3331,7 +4711,7 @@ 41: 'whitewater', # Kayaking/Rafting 42: 'skate_skiing', # Cross Country Skiing 43: 'yoga', # Training - 44: 'pilates', # Training + 44: 'pilates', # Fitness Equipment 45: 'indoor_running', # Run 46: 'gravel_cycling', # Cycling 47: 'e_bike_mountain', # Cycling @@ -3347,6 +4727,34 @@ 57: 'apnea_hunting', # Diving 58: 'virtual_activity', 59: 'obstacle', # Used for events where participants run, crawl through mud, climb over walls, etc. + 62: 'breathing', + 65: 'sail_race', # Sailing + 67: 'ultra', # Ultramarathon + 68: 'indoor_climbing', # Climbing + 69: 'bouldering', # Climbing + 70: 'hiit', # High Intensity Interval Training + 73: 'amrap', # HIIT + 74: 'emom', # HIIT + 75: 'tabata', # HIIT + 84: 'pickleball', # Racket + 85: 'padel', # Racket + 86: 'indoor_wheelchair_walk', + 87: 'indoor_wheelchair_run', + 88: 'indoor_hand_cycling', + 94: 'squash', + 95: 'badminton', + 96: 'racquetball', + 97: 'table_tennis', + 110: 'fly_canopy', # Flying + 111: 'fly_paraglide', # Flying + 112: 'fly_paramotor', # Flying + 113: 'fly_pressurized', # Flying + 114: 'fly_navigate', # Flying + 115: 'fly_timer', # Flying + 116: 'fly_altimeter', # Flying + 117: 'fly_wx', # Flying + 118: 'fly_vfr', # Flying + 119: 'fly_ifr', # Flying 254: 'all', }, ), @@ -3364,6 +4772,47 @@ 0x00000080: 'half_horizontal_top_split', }, ), + 'suspension_exercise_name': FieldType( + name='suspension_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'chest_fly', + 1: 'chest_press', + 2: 'crunch', + 3: 'curl', + 4: 'dip', + 5: 'face_pull', + 6: 'glute_bridge', + 7: 'hamstring_curl', + 8: 'hip_drop', + 9: 'inverted_row', + 10: 'knee_drive_jump', + 11: 'knee_to_chest', + 12: 'lat_pullover', + 13: 'lunge', + 14: 'mountain_climber', + 15: 'pendulum', + 16: 'pike', + 17: 'plank', + 18: 'power_pull', + 19: 'pull_up', + 20: 'push_up', + 21: 'reverse_mountain_climber', + 22: 'reverse_plank', + 23: 'rollout', + 24: 'row', + 25: 'side_lunge', + 26: 'side_plank', + 27: 'single_leg_deadlift', + 28: 'single_leg_squat', + 29: 'sit_up', + 30: 'split', + 31: 'squat', + 32: 'squat_jump', + 33: 'tricep_press', + 34: 'y_fly', + }, + ), 'swim_stroke': FieldType( name='swim_stroke', base_type=BASE_TYPES[0x00], # enum @@ -3375,6 +4824,8 @@ 4: 'drill', 5: 'mixed', 6: 'im', # IM is a mixed interval containing the same number of lengths for each of: Butterfly, Backstroke, Breaststroke, Freestyle, swam in that order. + 7: 'im_by_round', # For repeated workout steps, a new individual medly stroke is used for each round. + 8: 'rimo', # Reverse IM Order }, ), 'switch': FieldType( @@ -3386,6 +4837,15 @@ 2: 'auto', }, ), + 'tap_sensitivity': FieldType( + name='tap_sensitivity', + base_type=BASE_TYPES[0x00], # enum + values={ + 0: 'high', + 1: 'medium', + 2: 'low', + }, + ), 'time_into_day': FieldType( # number of seconds into the day since 00:00:00 UTC name='time_into_day', base_type=BASE_TYPES[0x86], # uint32 @@ -3523,6 +4983,13 @@ 2: 'fitness_equipment', }, ), + 'tire_exercise_name': FieldType( + name='tire_exercise_name', + base_type=BASE_TYPES[0x84], # uint16 + values={ + 0: 'flip', + }, + ), 'tissue_model_type': FieldType( name='tissue_model_type', base_type=BASE_TYPES[0x00], # enum @@ -3557,6 +5024,13 @@ 10: 'weighted_squat_plank_push_up', 11: 'standing_t_rotation_balance', 12: 'weighted_standing_t_rotation_balance', + 13: 'barbell_burpee', + 15: 'burpee_box_jump_over_yes_literally_jumping_over_the_box', + 16: 'burpee_box_jump_step_up_over', + 17: 'lateral_barbell_burpee', + 18: 'total_body_burpee_over_bar', + 19: 'burpee_box_jump_over', + 20: 'burpee_wheelchair', }, ), 'triceps_extension_exercise_name': FieldType( @@ -3604,6 +5078,10 @@ 38: 'triceps_extension_on_floor', 39: 'triceps_pressdown', 40: 'weighted_dip', + 41: 'alternating_dumbbell_lying_triceps_extension', + 42: 'triceps_press', + 43: 'dumbbell_kickback_wheelchair', + 44: 'overhead_dumbbell_triceps_extension_wheelchair', }, ), 'turn_type': FieldType( @@ -3682,7 +5160,7 @@ 13: 'neck_rotations', 14: 'opposite_arm_and_leg_balance', 15: 'reach_roll_and_lift', - 16: 'scorpion', + 16: 'scorpion', # Deprecated do not use 17: 'shoulder_circles', 18: 'side_to_side_leg_swings', 19: 'sleeper_stretch', @@ -3697,6 +5175,66 @@ 28: 'walking_leg_cradles', 29: 'walkout', 30: 'walkout_from_push_up_position', + 31: 'biceps_stretch', + 32: 'glutes_stretch', + 33: 'standing_hamstring_stretch', + 34: 'stretch_90_90', + 35: 'stretch_abs', + 36: 'stretch_butterfly', + 37: 'stretch_calf', + 38: 'stretch_cat_cow', + 39: 'stretch_childs_pose', + 40: 'stretch_cobra', + 41: 'stretch_forearms', + 42: 'stretch_forward_glutes', + 43: 'stretch_front_split', + 44: 'stretch_hamstring', + 45: 'stretch_hip_flexor_and_quad', + 46: 'stretch_lat', + 47: 'stretch_levator_scapulae', + 48: 'stretch_lunge_with_spinal_twist', + 49: 'stretch_lunging_hip_flexor', + 50: 'stretch_lying_abduction', + 51: 'stretch_lying_it_band', + 52: 'stretch_lying_knee_to_chest', + 53: 'stretch_lying_piriformis', + 54: 'stretch_lying_spinal_twist', + 55: 'stretch_neck', + 56: 'stretch_obliques', + 57: 'stretch_over_under_shoulder', + 58: 'stretch_pectoral', + 59: 'stretch_pigeon_pose', + 60: 'stretch_piriformis', + 61: 'stretch_quad', + 62: 'stretch_scorpion', + 63: 'stretch_shoulder', + 64: 'stretch_side', + 65: 'stretch_side_lunge', + 66: 'stretch_side_split', + 67: 'stretch_standing_it_band', + 68: 'stretch_straddle', + 69: 'stretch_triceps', + 70: 'stretch_wall_chest_and_shoulder', + 71: 'neck_rotations_wheelchair', + 72: 'half_kneeling_arm_rotation', + 73: 'three_way_ankle_mobilization', + 74: 'ninety_ninety_hip_switch', # 90_90_hip_switch + 75: 'active_frog', + 76: 'shoulder_sweeps', + 77: 'ankle_lunges', + 78: 'back_roll_foam_roller', + 79: 'bear_crawl', + 80: 'latissimus_dorsi_foam_roll', + 81: 'reverse_t_hip_opener', + 82: 'shoulder_rolls', + 83: 'chest_openers', + 84: 'triceps_stretch', + 85: 'upper_back_stretch', + 86: 'hip_circles', + 87: 'ankle_stretch', + 88: 'marching_in_place', + 89: 'triceps_stretch_wheelchair', + 90: 'upper_back_stretch_wheelchair', }, ), 'watchface_mode': FieldType( @@ -3899,6 +5437,7 @@ 27: 'repeat_until_training_peaks_tss', 28: 'repetition_time', 29: 'reps', + 31: 'time_only', }, ), 'wkt_step_target': FieldType( @@ -3930,7 +5469,7 @@ 0x00000004: 'fitness_equipment', 0x00000008: 'firstbeat', 0x00000010: 'new_leaf', - 0x00000020: 'tcx', # For backwards compatibility. Watch should add missing id fields then clear flag. + 0x00000020: 'tcx', # For backwards compatibility. Watch should add missing id fields then clear flag. 0x00000080: 'speed', # Speed source required for workout step. 0x00000100: 'heart_rate', # Heart rate source required for workout step. 0x00000200: 'distance', # Distance source required for workout step. @@ -3974,7 +5513,7 @@ MESSAGE_TYPES = { - # **************************** Common Messages ***************************** + # ************************************ ************************************ 0: MessageType( # Must be first message in file. name='file_id', mesg_num=0, @@ -3994,6 +5533,19 @@ type=BASE_TYPES[0x84], # uint16 def_num=2, subfields=( + SubField( + name='favero_product', + def_num=2, + type=FIELD_TYPES['favero_product'], + ref_fields=( + ReferenceField( + name='manufacturer', + def_num=1, + value='favero_electronics', + raw_value=263, + ), + ), + ), SubField( name='garmin_product', def_num=2, @@ -4017,18 +5569,11 @@ value='dynastream_oem', raw_value=13, ), - ) - ), - SubField( - name='strava_product', - def_num=2, - type=FIELD_TYPES['strava_product'], - ref_fields=( ReferenceField( name='manufacturer', def_num=1, - value='strava', - raw_value=265, + value='tacx', + raw_value=89, ), ), ), @@ -4056,813 +5601,543 @@ ), }, ), - - - # ************************************ ************************************ - 1: MessageType( - name='capabilities', - mesg_num=1, + 49: MessageType( + name='file_creator', + mesg_num=49, fields={ - 0: Field( # Use language_bits_x types where x is index of array. - name='languages', - type=BASE_TYPES[0x0A], # uint8z + 0: Field( + name='software_version', + type=BASE_TYPES[0x84], # uint16 def_num=0, ), - 1: Field( # Use sport_bits_x types where x is index of array. - name='sports', - type=FIELD_TYPES['sport_bits_0'], + 1: Field( + name='hardware_version', + type=BASE_TYPES[0x02], # uint8 def_num=1, ), - 21: Field( - name='workouts_supported', - type=FIELD_TYPES['workout_capabilities'], - def_num=21, - ), - 23: Field( - name='connectivity_supported', - type=FIELD_TYPES['connectivity_capabilities'], - def_num=23, - ), }, ), - 4: MessageType( - name='hrm_profile', - mesg_num=4, + 162: MessageType( + name='timestamp_correlation', + mesg_num=162, fields={ - 0: Field( - name='enabled', - type=FIELD_TYPES['bool'], + 0: Field( # Fractional part of the UTC timestamp at the time the system timestamp was recorded. + name='fractional_timestamp', + type=BASE_TYPES[0x84], # uint16 def_num=0, + scale=32768, + units='s', ), - 1: Field( - name='hrm_ant_id', - type=BASE_TYPES[0x8B], # uint16z + 1: Field( # Whole second part of the system timestamp + name='system_timestamp', + type=FIELD_TYPES['date_time'], def_num=1, + units='s', ), - 2: Field( - name='log_hrv', - type=FIELD_TYPES['bool'], + 2: Field( # Fractional part of the system timestamp + name='fractional_system_timestamp', + type=BASE_TYPES[0x84], # uint16 def_num=2, + scale=32768, + units='s', ), - 3: Field( - name='hrm_ant_id_trans_type', - type=BASE_TYPES[0x0A], # uint8z + 3: Field( # timestamp epoch expressed in local time used to convert timestamps to local time + name='local_timestamp', + type=FIELD_TYPES['local_date_time'], def_num=3, + units='s', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 4: Field( # Millisecond part of the UTC timestamp at the time the system timestamp was recorded. + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + units='ms', ), - }, - ), - 5: MessageType( - name='sdm_profile', - mesg_num=5, - fields={ - 0: Field( - name='enabled', - type=FIELD_TYPES['bool'], - def_num=0, - ), - 1: Field( - name='sdm_ant_id', - type=BASE_TYPES[0x8B], # uint16z - def_num=1, - ), - 2: Field( - name='sdm_cal_factor', + 5: Field( # Millisecond part of the system timestamp + name='system_timestamp_ms', type=BASE_TYPES[0x84], # uint16 - def_num=2, - scale=10, - units='%', - ), - 3: Field( - name='odometer', - type=BASE_TYPES[0x86], # uint32 - def_num=3, - scale=100, - units='m', - ), - 4: Field( # Use footpod for speed source instead of GPS - name='speed_source', - type=FIELD_TYPES['bool'], - def_num=4, - ), - 5: Field( - name='sdm_ant_id_trans_type', - type=BASE_TYPES[0x0A], # uint8z def_num=5, + units='ms', ), - 7: Field( # Rollover counter that can be used to extend the odometer - name='odometer_rollover', - type=BASE_TYPES[0x02], # uint8 - def_num=7, - ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, - ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of UTC timestamp at the time the system timestamp was recorded. }, ), - 6: MessageType( - name='bike_profile', - mesg_num=6, + + + # ************************* Activity File Messages ************************* + 18: MessageType( + name='session', + mesg_num=18, fields={ - 0: Field( - name='name', - type=BASE_TYPES[0x07], # string + 0: Field( # session + name='event', + type=FIELD_TYPES['event'], def_num=0, ), - 1: Field( - name='sport', - type=FIELD_TYPES['sport'], + 1: Field( # stop + name='event_type', + type=FIELD_TYPES['event_type'], def_num=1, ), 2: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], + name='start_time', + type=FIELD_TYPES['date_time'], def_num=2, ), 3: Field( - name='odometer', - type=BASE_TYPES[0x86], # uint32 + name='start_position_lat', + type=BASE_TYPES[0x85], # sint32 def_num=3, - scale=100, - units='m', + units='semicircles', ), 4: Field( - name='bike_spd_ant_id', - type=BASE_TYPES[0x8B], # uint16z + name='start_position_long', + type=BASE_TYPES[0x85], # sint32 def_num=4, + units='semicircles', ), 5: Field( - name='bike_cad_ant_id', - type=BASE_TYPES[0x8B], # uint16z + name='sport', + type=FIELD_TYPES['sport'], def_num=5, ), 6: Field( - name='bike_spdcad_ant_id', - type=BASE_TYPES[0x8B], # uint16z + name='sub_sport', + type=FIELD_TYPES['sub_sport'], def_num=6, ), - 7: Field( - name='bike_power_ant_id', - type=BASE_TYPES[0x8B], # uint16z + 7: Field( # Time (includes pauses) + name='total_elapsed_time', + type=BASE_TYPES[0x86], # uint32 def_num=7, + scale=1000, + units='s', ), - 8: Field( - name='custom_wheelsize', - type=BASE_TYPES[0x84], # uint16 + 8: Field( # Timer Time (excludes pauses) + name='total_timer_time', + type=BASE_TYPES[0x86], # uint32 def_num=8, scale=1000, - units='m', + units='s', ), 9: Field( - name='auto_wheelsize', - type=BASE_TYPES[0x84], # uint16 + name='total_distance', + type=BASE_TYPES[0x86], # uint32 def_num=9, - scale=1000, + scale=100, units='m', ), 10: Field( - name='bike_weight', - type=BASE_TYPES[0x84], # uint16 + name='total_cycles', + type=BASE_TYPES[0x86], # uint32 def_num=10, - scale=10, - units='kg', + units='cycles', + subfields=( + SubField( + name='total_strides', + def_num=10, + type=BASE_TYPES[0x86], # uint32 + units='strides', + ref_fields=( + ReferenceField( + name='sport', + def_num=5, + value='running', + raw_value=1, + ), + ReferenceField( + name='sport', + def_num=5, + value='walking', + raw_value=11, + ), + ), + ), + SubField( + name='total_strokes', + def_num=10, + type=BASE_TYPES[0x86], # uint32 + units='strokes', + ref_fields=( + ReferenceField( + name='sport', + def_num=5, + value='cycling', + raw_value=2, + ), + ReferenceField( + name='sport', + def_num=5, + value='swimming', + raw_value=5, + ), + ReferenceField( + name='sport', + def_num=5, + value='rowing', + raw_value=15, + ), + ReferenceField( + name='sport', + def_num=5, + value='stand_up_paddleboarding', + raw_value=37, + ), + ), + ), + ), ), 11: Field( - name='power_cal_factor', + name='total_calories', type=BASE_TYPES[0x84], # uint16 def_num=11, - scale=10, - units='%', - ), - 12: Field( - name='auto_wheel_cal', - type=FIELD_TYPES['bool'], - def_num=12, + units='kcal', ), 13: Field( - name='auto_power_zero', - type=FIELD_TYPES['bool'], + name='total_fat_calories', + type=BASE_TYPES[0x84], # uint16 def_num=13, + units='kcal', ), - 14: Field( - name='id', - type=BASE_TYPES[0x02], # uint8 + 14: Field( # total_distance / total_timer_time + name='avg_speed', + type=BASE_TYPES[0x84], # uint16 def_num=14, + scale=1000, + units='m/s', + components=( + ComponentField( + name='enhanced_avg_speed', + def_num=124, + scale=1000, + units='m/s', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), ), 15: Field( - name='spd_enabled', - type=FIELD_TYPES['bool'], + name='max_speed', + type=BASE_TYPES[0x84], # uint16 def_num=15, + scale=1000, + units='m/s', + components=( + ComponentField( + name='enhanced_max_speed', + def_num=125, + scale=1000, + units='m/s', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), ), - 16: Field( - name='cad_enabled', - type=FIELD_TYPES['bool'], + 16: Field( # average heart rate (excludes pause time) + name='avg_heart_rate', + type=BASE_TYPES[0x02], # uint8 def_num=16, + units='bpm', ), 17: Field( - name='spdcad_enabled', - type=FIELD_TYPES['bool'], + name='max_heart_rate', + type=BASE_TYPES[0x02], # uint8 def_num=17, + units='bpm', ), - 18: Field( - name='power_enabled', - type=FIELD_TYPES['bool'], - def_num=18, - ), - 19: Field( - name='crank_length', + 18: Field( # total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time + name='avg_cadence', type=BASE_TYPES[0x02], # uint8 - def_num=19, - scale=2, - offset=-110, - units='mm', - ), - 20: Field( - name='enabled', - type=FIELD_TYPES['bool'], - def_num=20, - ), - 21: Field( - name='bike_spd_ant_id_trans_type', - type=BASE_TYPES[0x0A], # uint8z + def_num=18, + units='rpm', + subfields=( + SubField( + name='avg_running_cadence', + def_num=18, + type=BASE_TYPES[0x02], # uint8 + units='strides/min', + ref_fields=( + ReferenceField( + name='sport', + def_num=5, + value='running', + raw_value=1, + ), + ), + ), + ), + ), + 19: Field( + name='max_cadence', + type=BASE_TYPES[0x02], # uint8 + def_num=19, + units='rpm', + subfields=( + SubField( + name='max_running_cadence', + def_num=19, + type=BASE_TYPES[0x02], # uint8 + units='strides/min', + ref_fields=( + ReferenceField( + name='sport', + def_num=5, + value='running', + raw_value=1, + ), + ), + ), + ), + ), + 20: Field( # total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time + name='avg_power', + type=BASE_TYPES[0x84], # uint16 + def_num=20, + units='watts', + ), + 21: Field( + name='max_power', + type=BASE_TYPES[0x84], # uint16 def_num=21, + units='watts', ), 22: Field( - name='bike_cad_ant_id_trans_type', - type=BASE_TYPES[0x0A], # uint8z + name='total_ascent', + type=BASE_TYPES[0x84], # uint16 def_num=22, + units='m', ), 23: Field( - name='bike_spdcad_ant_id_trans_type', - type=BASE_TYPES[0x0A], # uint8z + name='total_descent', + type=BASE_TYPES[0x84], # uint16 def_num=23, + units='m', ), 24: Field( - name='bike_power_ant_id_trans_type', - type=BASE_TYPES[0x0A], # uint8z - def_num=24, - ), - 37: Field( # Rollover counter that can be used to extend the odometer - name='odometer_rollover', + name='total_training_effect', type=BASE_TYPES[0x02], # uint8 - def_num=37, + def_num=24, + scale=10, ), - 38: Field( # Number of front gears - name='front_gear_num', - type=BASE_TYPES[0x0A], # uint8z - def_num=38, + 25: Field( + name='first_lap_index', + type=BASE_TYPES[0x84], # uint16 + def_num=25, ), - 39: Field( # Number of teeth on each gear 0 is innermost - name='front_gear', - type=BASE_TYPES[0x0A], # uint8z - def_num=39, + 26: Field( + name='num_laps', + type=BASE_TYPES[0x84], # uint16 + def_num=26, ), - 40: Field( # Number of rear gears - name='rear_gear_num', - type=BASE_TYPES[0x0A], # uint8z - def_num=40, + 27: Field( + name='event_group', + type=BASE_TYPES[0x02], # uint8 + def_num=27, ), - 41: Field( # Number of teeth on each gear 0 is innermost - name='rear_gear', - type=BASE_TYPES[0x0A], # uint8z - def_num=41, + 28: Field( + name='trigger', + type=FIELD_TYPES['session_trigger'], + def_num=28, ), - 44: Field( - name='shimano_di2_enabled', - type=FIELD_TYPES['bool'], - def_num=44, + 29: Field( # North east corner latitude + name='nec_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=29, + units='semicircles', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 30: Field( # North east corner longitude + name='nec_long', + type=BASE_TYPES[0x85], # sint32 + def_num=30, + units='semicircles', ), - }, - ), - 8: MessageType( - name='hr_zone', - mesg_num=8, - fields={ - 1: Field( - name='high_bpm', - type=BASE_TYPES[0x02], # uint8 - def_num=1, - units='bpm', + 31: Field( # South west corner latitude + name='swc_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=31, + units='semicircles', ), - 2: Field( - name='name', - type=BASE_TYPES[0x07], # string - def_num=2, + 32: Field( # South west corner longitude + name='swc_long', + type=BASE_TYPES[0x85], # sint32 + def_num=32, + units='semicircles', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 33: Field( # # of lengths of swim pool + name='num_lengths', + type=BASE_TYPES[0x84], # uint16 + def_num=33, + units='lengths', ), - }, - ), - 9: MessageType( - name='power_zone', - mesg_num=9, - fields={ - 1: Field( - name='high_value', + 34: Field( + name='normalized_power', type=BASE_TYPES[0x84], # uint16 - def_num=1, + def_num=34, units='watts', ), - 2: Field( - name='name', - type=BASE_TYPES[0x07], # string - def_num=2, - ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, - ), - }, - ), - 10: MessageType( - name='met_zone', - mesg_num=10, - fields={ - 1: Field( - name='high_bpm', - type=BASE_TYPES[0x02], # uint8 - def_num=1, - ), - 2: Field( - name='calories', + 35: Field( + name='training_stress_score', type=BASE_TYPES[0x84], # uint16 - def_num=2, + def_num=35, scale=10, - units='kcal/min', + units='tss', ), - 3: Field( - name='fat_calories', - type=BASE_TYPES[0x02], # uint8 - def_num=3, - scale=10, - units='kcal/min', + 36: Field( + name='intensity_factor', + type=BASE_TYPES[0x84], # uint16 + def_num=36, + scale=1000, + units='if', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 37: Field( + name='left_right_balance', + type=FIELD_TYPES['left_right_balance_100'], + def_num=37, ), - }, - ), - 12: MessageType( - name='sport', - mesg_num=12, - fields={ - 0: Field( - name='sport', - type=FIELD_TYPES['sport'], - def_num=0, + 38: Field( + name='end_position_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=38, + units='semicircles', ), - 1: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], - def_num=1, + 39: Field( + name='end_position_long', + type=BASE_TYPES[0x85], # sint32 + def_num=39, + units='semicircles', ), - 3: Field( - name='name', - type=BASE_TYPES[0x07], # string - def_num=3, + 41: Field( + name='avg_stroke_count', + type=BASE_TYPES[0x86], # uint32 + def_num=41, + scale=10, + units='strokes/lap', ), - }, - ), - 18: MessageType( - name='session', - mesg_num=18, - fields={ - 0: Field( # session - name='event', - type=FIELD_TYPES['event'], - def_num=0, - ), - 1: Field( # stop - name='event_type', - type=FIELD_TYPES['event_type'], - def_num=1, - ), - 2: Field( - name='start_time', - type=FIELD_TYPES['date_time'], - def_num=2, - ), - 3: Field( - name='start_position_lat', - type=BASE_TYPES[0x85], # sint32 - def_num=3, - units='semicircles', - ), - 4: Field( - name='start_position_long', - type=BASE_TYPES[0x85], # sint32 - def_num=4, - units='semicircles', - ), - 5: Field( - name='sport', - type=FIELD_TYPES['sport'], - def_num=5, - ), - 6: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], - def_num=6, - ), - 7: Field( # Time (includes pauses) - name='total_elapsed_time', - type=BASE_TYPES[0x86], # uint32 - def_num=7, - scale=1000, - units='s', + 42: Field( + name='avg_stroke_distance', + type=BASE_TYPES[0x84], # uint16 + def_num=42, + scale=100, + units='m', ), - 8: Field( # Timer Time (excludes pauses) - name='total_timer_time', - type=BASE_TYPES[0x86], # uint32 - def_num=8, - scale=1000, - units='s', + 43: Field( + name='swim_stroke', + type=FIELD_TYPES['swim_stroke'], + def_num=43, + units='swim_stroke', ), - 9: Field( - name='total_distance', - type=BASE_TYPES[0x86], # uint32 - def_num=9, + 44: Field( + name='pool_length', + type=BASE_TYPES[0x84], # uint16 + def_num=44, scale=100, units='m', ), - 10: Field( - name='total_cycles', - type=BASE_TYPES[0x86], # uint32 - def_num=10, - units='cycles', - subfields=( - SubField( - name='total_strides', - def_num=10, - type=BASE_TYPES[0x86], # uint32 - units='strides', - ref_fields=( - ReferenceField( - name='sport', - def_num=5, - value='running', - raw_value=1, - ), - ReferenceField( - name='sport', - def_num=5, - value='walking', - raw_value=11, - ), - ), - ), - ), - ), - 11: Field( - name='total_calories', + 45: Field( + name='threshold_power', type=BASE_TYPES[0x84], # uint16 - def_num=11, - units='kcal', + def_num=45, + units='watts', ), - 13: Field( - name='total_fat_calories', + 46: Field( + name='pool_length_unit', + type=FIELD_TYPES['display_measure'], + def_num=46, + ), + 47: Field( # # of active lengths of swim pool + name='num_active_lengths', type=BASE_TYPES[0x84], # uint16 - def_num=13, - units='kcal', + def_num=47, + units='lengths', ), - 14: Field( # total_distance / total_timer_time - name='avg_speed', + 48: Field( + name='total_work', + type=BASE_TYPES[0x86], # uint32 + def_num=48, + units='J', + ), + 49: Field( + name='avg_altitude', type=BASE_TYPES[0x84], # uint16 - def_num=14, - scale=1000, - units='m/s', + def_num=49, + scale=5, + offset=500, + units='m', components=( ComponentField( - name='enhanced_avg_speed', - def_num=124, - scale=1000, - units='m/s', + name='enhanced_avg_altitude', + def_num=126, + scale=5, + offset=500, + units='m', accumulate=False, bits=16, bit_offset=0, ), ), ), - 15: Field( - name='max_speed', + 50: Field( + name='max_altitude', type=BASE_TYPES[0x84], # uint16 - def_num=15, - scale=1000, - units='m/s', + def_num=50, + scale=5, + offset=500, + units='m', components=( ComponentField( - name='enhanced_max_speed', - def_num=125, - scale=1000, - units='m/s', + name='enhanced_max_altitude', + def_num=128, + scale=5, + offset=500, + units='m', accumulate=False, bits=16, bit_offset=0, ), ), ), - 16: Field( # average heart rate (excludes pause time) - name='avg_heart_rate', + 51: Field( + name='gps_accuracy', type=BASE_TYPES[0x02], # uint8 - def_num=16, - units='bpm', + def_num=51, + units='m', ), - 17: Field( - name='max_heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=17, - units='bpm', + 52: Field( + name='avg_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=52, + scale=100, + units='%', ), - 18: Field( # total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time - name='avg_cadence', - type=BASE_TYPES[0x02], # uint8 - def_num=18, - units='rpm', - subfields=( - SubField( - name='avg_running_cadence', - def_num=18, - type=BASE_TYPES[0x02], # uint8 - units='strides/min', - ref_fields=( - ReferenceField( - name='sport', - def_num=5, - value='running', - raw_value=1, - ), - ), - ), - ), + 53: Field( + name='avg_pos_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=53, + scale=100, + units='%', ), - 19: Field( - name='max_cadence', - type=BASE_TYPES[0x02], # uint8 - def_num=19, - units='rpm', - subfields=( - SubField( - name='max_running_cadence', - def_num=19, - type=BASE_TYPES[0x02], # uint8 - units='strides/min', - ref_fields=( - ReferenceField( - name='sport', - def_num=5, - value='running', - raw_value=1, - ), - ), - ), - ), + 54: Field( + name='avg_neg_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=54, + scale=100, + units='%', ), - 20: Field( # total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time - name='avg_power', - type=BASE_TYPES[0x84], # uint16 - def_num=20, - units='watts', + 55: Field( + name='max_pos_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=55, + scale=100, + units='%', ), - 21: Field( - name='max_power', - type=BASE_TYPES[0x84], # uint16 - def_num=21, - units='watts', - ), - 22: Field( - name='total_ascent', - type=BASE_TYPES[0x84], # uint16 - def_num=22, - units='m', - ), - 23: Field( - name='total_descent', - type=BASE_TYPES[0x84], # uint16 - def_num=23, - units='m', - ), - 24: Field( - name='total_training_effect', - type=BASE_TYPES[0x02], # uint8 - def_num=24, - scale=10, - ), - 25: Field( - name='first_lap_index', - type=BASE_TYPES[0x84], # uint16 - def_num=25, - ), - 26: Field( - name='num_laps', - type=BASE_TYPES[0x84], # uint16 - def_num=26, - ), - 27: Field( - name='event_group', - type=BASE_TYPES[0x02], # uint8 - def_num=27, - ), - 28: Field( - name='trigger', - type=FIELD_TYPES['session_trigger'], - def_num=28, - ), - 29: Field( - name='nec_lat', - type=BASE_TYPES[0x85], # sint32 - def_num=29, - units='semicircles', - ), - 30: Field( - name='nec_long', - type=BASE_TYPES[0x85], # sint32 - def_num=30, - units='semicircles', - ), - 31: Field( - name='swc_lat', - type=BASE_TYPES[0x85], # sint32 - def_num=31, - units='semicircles', - ), - 32: Field( - name='swc_long', - type=BASE_TYPES[0x85], # sint32 - def_num=32, - units='semicircles', - ), - 34: Field( - name='normalized_power', - type=BASE_TYPES[0x84], # uint16 - def_num=34, - units='watts', - ), - 35: Field( - name='training_stress_score', - type=BASE_TYPES[0x84], # uint16 - def_num=35, - scale=10, - units='tss', - ), - 36: Field( - name='intensity_factor', - type=BASE_TYPES[0x84], # uint16 - def_num=36, - scale=1000, - units='if', - ), - 37: Field( - name='left_right_balance', - type=FIELD_TYPES['left_right_balance_100'], - def_num=37, - ), - 41: Field( - name='avg_stroke_count', - type=BASE_TYPES[0x86], # uint32 - def_num=41, - scale=10, - units='strokes/lap', - ), - 42: Field( - name='avg_stroke_distance', - type=BASE_TYPES[0x84], # uint16 - def_num=42, - scale=100, - units='m', - ), - 43: Field( - name='swim_stroke', - type=FIELD_TYPES['swim_stroke'], - def_num=43, - units='swim_stroke', - ), - 44: Field( - name='pool_length', - type=BASE_TYPES[0x84], # uint16 - def_num=44, - scale=100, - units='m', - ), - 45: Field( - name='threshold_power', - type=BASE_TYPES[0x84], # uint16 - def_num=45, - units='watts', - ), - 46: Field( - name='pool_length_unit', - type=FIELD_TYPES['display_measure'], - def_num=46, - ), - 47: Field( # # of active lengths of swim pool - name='num_active_lengths', - type=BASE_TYPES[0x84], # uint16 - def_num=47, - units='lengths', - ), - 48: Field( - name='total_work', - type=BASE_TYPES[0x86], # uint32 - def_num=48, - units='J', - ), - 49: Field( - name='avg_altitude', - type=BASE_TYPES[0x84], # uint16 - def_num=49, - scale=5, - offset=500, - units='m', - components=( - ComponentField( - name='enhanced_avg_altitude', - def_num=126, - scale=5, - offset=500, - units='m', - accumulate=False, - bits=16, - bit_offset=0, - ), - ), - ), - 50: Field( - name='max_altitude', - type=BASE_TYPES[0x84], # uint16 - def_num=50, - scale=5, - offset=500, - units='m', - components=( - ComponentField( - name='enhanced_max_altitude', - def_num=128, - scale=5, - offset=500, - units='m', - accumulate=False, - bits=16, - bit_offset=0, - ), - ), - ), - 51: Field( - name='gps_accuracy', - type=BASE_TYPES[0x02], # uint8 - def_num=51, - units='m', - ), - 52: Field( - name='avg_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=52, - scale=100, - units='%', - ), - 53: Field( - name='avg_pos_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=53, - scale=100, - units='%', - ), - 54: Field( - name='avg_neg_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=54, - scale=100, - units='%', - ), - 55: Field( - name='max_pos_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=55, - scale=100, - units='%', - ), - 56: Field( - name='max_neg_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=56, - scale=100, - units='%', + 56: Field( + name='max_neg_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=56, + scale=100, + units='%', ), 57: Field( name='avg_temperature', @@ -5137,6 +6412,11 @@ scale=2, units='percent', ), + 110: Field( # Sport name from associated sport mesg + name='sport_profile_name', + type=BASE_TYPES[0x07], # string + def_num=110, + ), 111: Field( name='sport_index', type=BASE_TYPES[0x02], # uint8 @@ -5187,7 +6467,7 @@ scale=0.7111111, units='degrees', ), - 119: Field( # Average right power phase peak angles data value indexes defined by power_phase_type. + 119: Field( # Average right power phase peak angles data value indexes defined by power_phase_type. name='avg_right_power_phase_peak', type=BASE_TYPES[0x02], # uint8 def_num=119, @@ -5309,32 +6589,259 @@ scale=1000, units='m/s', ), - 253: FIELD_TYPE_TIMESTAMP, # Sesson end time. - 254: Field( # Selected bit is set for the current session. - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 140: Field( # 0 if above water + name='avg_depth', + type=BASE_TYPES[0x86], # uint32 + def_num=140, + scale=1000, + units='m', ), - }, - ), - 19: MessageType( - name='lap', - mesg_num=19, - fields={ - 0: Field( - name='event', - type=FIELD_TYPES['event'], - def_num=0, + 141: Field( # 0 if above water + name='max_depth', + type=BASE_TYPES[0x86], # uint32 + def_num=141, + scale=1000, + units='m', ), - 1: Field( - name='event_type', - type=FIELD_TYPES['event_type'], - def_num=1, + 142: Field( # Time since end of last dive + name='surface_interval', + type=BASE_TYPES[0x86], # uint32 + def_num=142, + units='s', ), - 2: Field( - name='start_time', - type=FIELD_TYPES['date_time'], - def_num=2, + 143: Field( + name='start_cns', + type=BASE_TYPES[0x02], # uint8 + def_num=143, + units='percent', + ), + 144: Field( + name='end_cns', + type=BASE_TYPES[0x02], # uint8 + def_num=144, + units='percent', + ), + 145: Field( + name='start_n2', + type=BASE_TYPES[0x84], # uint16 + def_num=145, + units='percent', + ), + 146: Field( + name='end_n2', + type=BASE_TYPES[0x84], # uint16 + def_num=146, + units='percent', + ), + 147: Field( + name='avg_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=147, + components=( + ComponentField( + name='enhanced_avg_respiration_rate', + def_num=169, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 148: Field( + name='max_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=148, + components=( + ComponentField( + name='enhanced_max_respiration_rate', + def_num=170, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 149: Field( + name='min_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=149, + components=( + ComponentField( + name='enhanced_min_respiration_rate', + def_num=180, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 150: Field( + name='min_temperature', + type=BASE_TYPES[0x01], # sint8 + def_num=150, + units='C', + ), + 155: Field( + name='o2_toxicity', + type=BASE_TYPES[0x84], # uint16 + def_num=155, + units='OTUs', + ), + 156: Field( + name='dive_number', + type=BASE_TYPES[0x86], # uint32 + def_num=156, + ), + 168: Field( + name='training_load_peak', + type=BASE_TYPES[0x85], # sint32 + def_num=168, + scale=65536, + ), + 169: Field( + name='enhanced_avg_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=169, + scale=100, + units='Breaths/min', + ), + 170: Field( + name='enhanced_max_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=170, + scale=100, + units='Breaths/min', + ), + 180: Field( + name='enhanced_min_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=180, + scale=100, + ), + 181: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='total_grit', + type=BASE_TYPES[0x88], # float32 + def_num=181, + units='kGrit', + ), + 182: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='total_flow', + type=BASE_TYPES[0x88], # float32 + def_num=182, + units='Flow', + ), + 183: Field( + name='jump_count', + type=BASE_TYPES[0x84], # uint16 + def_num=183, + ), + 186: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='avg_grit', + type=BASE_TYPES[0x88], # float32 + def_num=186, + units='kGrit', + ), + 187: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='avg_flow', + type=BASE_TYPES[0x88], # float32 + def_num=187, + units='Flow', + ), + 192: Field( # A 0-100 scale representing how a user felt while performing a workout. Low values are considered feeling bad, while high values are good. + name='workout_feel', + type=BASE_TYPES[0x02], # uint8 + def_num=192, + ), + 193: Field( # Common Borg CR10 / 0-10 RPE scale, multiplied 10x.. Aggregate score for all workouts in a single session. + name='workout_rpe', + type=BASE_TYPES[0x02], # uint8 + def_num=193, + ), + 194: Field( # Average SPO2 for the monitoring session + name='avg_spo2', + type=BASE_TYPES[0x02], # uint8 + def_num=194, + units='percent', + ), + 195: Field( # Average stress for the monitoring session + name='avg_stress', + type=BASE_TYPES[0x02], # uint8 + def_num=195, + units='percent', + ), + 197: Field( # Standard deviation of R-R interval (SDRR) - Heart rate variability measure most useful for wellness users. + name='sdrr_hrv', + type=BASE_TYPES[0x02], # uint8 + def_num=197, + units='mS', + ), + 198: Field( # Root mean square successive difference (RMSSD) - Heart rate variability measure most useful for athletes + name='rmssd_hrv', + type=BASE_TYPES[0x02], # uint8 + def_num=198, + units='mS', + ), + 199: Field( # fractional part of total_ascent + name='total_fractional_ascent', + type=BASE_TYPES[0x02], # uint8 + def_num=199, + scale=100, + units='m', + ), + 200: Field( # fractional part of total_descent + name='total_fractional_descent', + type=BASE_TYPES[0x02], # uint8 + def_num=200, + scale=100, + units='m', + ), + 208: Field( + name='avg_core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=208, + scale=100, + units='C', + ), + 209: Field( + name='min_core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=209, + scale=100, + units='C', + ), + 210: Field( + name='max_core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=210, + scale=100, + units='C', + ), + 253: FIELD_TYPE_TIMESTAMP, # Sesson end time. + 254: Field( # Selected bit is set for the current session. + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 19: MessageType( + name='lap', + mesg_num=19, + fields={ + 0: Field( + name='event', + type=FIELD_TYPES['event'], + def_num=0, + ), + 1: Field( + name='event_type', + type=FIELD_TYPES['event_type'], + def_num=1, + ), + 2: Field( + name='start_time', + type=FIELD_TYPES['date_time'], + def_num=2, ), 3: Field( name='start_position_lat', @@ -5407,6 +6914,38 @@ ), ), ), + SubField( + name='total_strokes', + def_num=10, + type=BASE_TYPES[0x86], # uint32 + units='strokes', + ref_fields=( + ReferenceField( + name='sport', + def_num=25, + value='cycling', + raw_value=2, + ), + ReferenceField( + name='sport', + def_num=25, + value='swimming', + raw_value=5, + ), + ReferenceField( + name='sport', + def_num=25, + value='rowing', + raw_value=15, + ), + ReferenceField( + name='sport', + def_num=25, + value='stand_up_paddleboarding', + raw_value=37, + ), + ), + ), ), ), 11: Field( @@ -5972,7 +7511,7 @@ scale=0.7111111, units='degrees', ), - 103: Field( # Average left power phase peak angles. Data value indexes defined by power_phase_type. + 103: Field( # Average left power phase peak angles. Data value indexes defined by power_phase_type. name='avg_left_power_phase_peak', type=BASE_TYPES[0x02], # uint8 def_num=103, @@ -5986,7 +7525,7 @@ scale=0.7111111, units='degrees', ), - 105: Field( # Average right power phase peak angles. Data value indexes defined by power_phase_type. + 105: Field( # Average right power phase peak angles. Data value indexes defined by power_phase_type. name='avg_right_power_phase_peak', type=BASE_TYPES[0x02], # uint8 def_num=105, @@ -6102,6 +7641,132 @@ scale=1000, units='m/s', ), + 122: Field( # 0 if above water + name='avg_depth', + type=BASE_TYPES[0x86], # uint32 + def_num=122, + scale=1000, + units='m', + ), + 123: Field( # 0 if above water + name='max_depth', + type=BASE_TYPES[0x86], # uint32 + def_num=123, + scale=1000, + units='m', + ), + 124: Field( + name='min_temperature', + type=BASE_TYPES[0x01], # sint8 + def_num=124, + units='C', + ), + 136: Field( + name='enhanced_avg_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=136, + scale=100, + units='Breaths/min', + ), + 137: Field( + name='enhanced_max_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=137, + scale=100, + units='Breaths/min', + ), + 147: Field( + name='avg_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=147, + components=( + ComponentField( + name='enhanced_avg_respiration_rate', + def_num=136, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 148: Field( + name='max_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=148, + components=( + ComponentField( + name='enhanced_max_respiration_rate', + def_num=137, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 149: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='total_grit', + type=BASE_TYPES[0x88], # float32 + def_num=149, + units='kGrit', + ), + 150: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='total_flow', + type=BASE_TYPES[0x88], # float32 + def_num=150, + units='Flow', + ), + 151: Field( + name='jump_count', + type=BASE_TYPES[0x84], # uint16 + def_num=151, + ), + 153: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='avg_grit', + type=BASE_TYPES[0x88], # float32 + def_num=153, + units='kGrit', + ), + 154: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='avg_flow', + type=BASE_TYPES[0x88], # float32 + def_num=154, + units='Flow', + ), + 156: Field( # fractional part of total_ascent + name='total_fractional_ascent', + type=BASE_TYPES[0x02], # uint8 + def_num=156, + scale=100, + units='m', + ), + 157: Field( # fractional part of total_descent + name='total_fractional_descent', + type=BASE_TYPES[0x02], # uint8 + def_num=157, + scale=100, + units='m', + ), + 158: Field( + name='avg_core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=158, + scale=100, + units='C', + ), + 159: Field( + name='min_core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=159, + scale=100, + units='C', + ), + 160: Field( + name='max_core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=160, + scale=100, + units='C', + ), 253: FIELD_TYPE_TIMESTAMP, # Lap end time. 254: Field( name='message_index', @@ -6221,7 +7886,7 @@ scale=100, units='%', ), - 10: Field( # Relative. 0 is none 254 is Max. + 10: Field( # Relative. 0 is none 254 is Max. name='resistance', type=BASE_TYPES[0x02], # uint8 def_num=10, @@ -6246,7 +7911,7 @@ def_num=13, units='C', ), - 17: Field( # Speed at 1s intervals. Timestamp field indicates time of last array element. + 17: Field( # Speed at 1s intervals. Timestamp field indicates time of last array element. name='speed_1s', type=BASE_TYPES[0x02], # uint8 def_num=17, @@ -6554,6 +8219,13 @@ scale=10, units='mm', ), + 87: Field( # Supports larger cycle sizes needed for paddlesports. Max cycle size: 655.35 + name='cycle_length16', + type=BASE_TYPES[0x84], # uint16 + def_num=87, + scale=100, + units='m', + ), 91: Field( # Includes atmospheric pressure name='absolute_pressure', type=BASE_TYPES[0x86], # uint32 @@ -6604,25 +8276,136 @@ def_num=98, units='percent', ), - 253: FIELD_TYPE_TIMESTAMP, - }, - ), - 21: MessageType( - name='event', - mesg_num=21, - fields={ - 0: Field( - name='event', - type=FIELD_TYPES['event'], - def_num=0, - ), - 1: Field( - name='event_type', - type=FIELD_TYPES['event_type'], - def_num=1, - ), - 2: Field( - name='data16', + 99: Field( + name='respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=99, + units='s', + components=( + ComponentField( + name='enhanced_respiration_rate', + def_num=108, + units='s', + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 108: Field( + name='enhanced_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=108, + scale=100, + units='Breaths/min', + ), + 114: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='grit', + type=BASE_TYPES[0x88], # float32 + def_num=114, + ), + 115: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='flow', + type=BASE_TYPES[0x88], # float32 + def_num=115, + ), + 116: Field( # Current Stress value + name='current_stress', + type=BASE_TYPES[0x84], # uint16 + def_num=116, + scale=100, + ), + 117: Field( + name='ebike_travel_range', + type=BASE_TYPES[0x84], # uint16 + def_num=117, + units='km', + ), + 118: Field( + name='ebike_battery_level', + type=BASE_TYPES[0x02], # uint8 + def_num=118, + units='percent', + ), + 119: Field( + name='ebike_assist_mode', + type=BASE_TYPES[0x02], # uint8 + def_num=119, + units='depends on sensor', + ), + 120: Field( + name='ebike_assist_level_percent', + type=BASE_TYPES[0x02], # uint8 + def_num=120, + units='percent', + ), + 123: Field( + name='air_time_remaining', + type=BASE_TYPES[0x86], # uint32 + def_num=123, + units='s', + ), + 124: Field( # Pressure-based surface air consumption + name='pressure_sac', + type=BASE_TYPES[0x84], # uint16 + def_num=124, + scale=100, + units='bar/min', + ), + 125: Field( # Volumetric surface air consumption + name='volume_sac', + type=BASE_TYPES[0x84], # uint16 + def_num=125, + scale=100, + units='L/min', + ), + 126: Field( # Respiratory minute volume + name='rmv', + type=BASE_TYPES[0x84], # uint16 + def_num=126, + scale=100, + units='L/min', + ), + 127: Field( + name='ascent_rate', + type=BASE_TYPES[0x85], # sint32 + def_num=127, + scale=1000, + units='m/s', + ), + 129: Field( # Current partial pressure of oxygen + name='po2', + type=BASE_TYPES[0x02], # uint8 + def_num=129, + scale=100, + units='percent', + ), + 139: Field( + name='core_temperature', + type=BASE_TYPES[0x84], # uint16 + def_num=139, + scale=100, + units='C', + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 21: MessageType( + name='event', + mesg_num=21, + fields={ + 0: Field( + name='event', + type=FIELD_TYPES['event'], + def_num=0, + ), + 1: Field( + name='event_type', + type=FIELD_TYPES['event_type'], + def_num=1, + ), + 2: Field( + name='data16', type=BASE_TYPES[0x84], # uint16 def_num=2, components=( @@ -6640,6 +8423,20 @@ type=BASE_TYPES[0x86], # uint32 def_num=3, subfields=( + SubField( + name='auto_activity_detect_duration', + def_num=3, + type=BASE_TYPES[0x84], # uint16 + units='min', + ref_fields=( + ReferenceField( + name='event', + def_num=0, + value='auto_activity_detect', + raw_value=54, + ), + ), + ), SubField( name='battery_level', def_num=3, @@ -6738,6 +8535,19 @@ ), ), ), + SubField( + name='dive_alert', + def_num=3, + type=FIELD_TYPES['dive_alert'], + ref_fields=( + ReferenceField( + name='event', + def_num=0, + value='dive_alert', + raw_value=56, + ), + ), + ), SubField( name='fitness_equipment_state', def_num=3, @@ -6856,6 +8666,51 @@ ), ), ), + SubField( # The first byte is the radar_threat_level_max, the second byte is the radar_threat_count, third bytes is the average approach speed, and the 4th byte is the max approach speed + name='radar_threat_alert', + def_num=3, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='event', + def_num=0, + value='radar_threat_alert', + raw_value=75, + ), + ), + components=( + ComponentField( + name='radar_threat_level_max', + def_num=21, + accumulate=False, + bits=8, + bit_offset=0, + ), + ComponentField( + name='radar_threat_count', + def_num=22, + accumulate=False, + bits=8, + bit_offset=8, + ), + ComponentField( + name='radar_threat_avg_approach_speed', + def_num=23, + scale=10, + accumulate=False, + bits=8, + bit_offset=16, + ), + ComponentField( + name='radar_threat_max_approach_speed', + def_num=24, + scale=10, + accumulate=False, + bits=8, + bit_offset=24, + ), + ), + ), SubField( # Indicates the rider position value. name='rider_position', def_num=3, @@ -6978,32 +8833,32 @@ type=BASE_TYPES[0x02], # uint8 def_num=4, ), - 7: Field( # Do not populate directly. Autogenerated by decoder for sport_point subfield components + 7: Field( # Do not populate directly. Autogenerated by decoder for sport_point subfield components name='score', type=BASE_TYPES[0x84], # uint16 def_num=7, ), - 8: Field( # Do not populate directly. Autogenerated by decoder for sport_point subfield components + 8: Field( # Do not populate directly. Autogenerated by decoder for sport_point subfield components name='opponent_score', type=BASE_TYPES[0x84], # uint16 def_num=8, ), - 9: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Front gear number. 1 is innermost. + 9: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Front gear number. 1 is innermost. name='front_gear_num', type=BASE_TYPES[0x0A], # uint8z def_num=9, ), - 10: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Number of front teeth. + 10: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Number of front teeth. name='front_gear', type=BASE_TYPES[0x0A], # uint8z def_num=10, ), - 11: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Rear gear number. 1 is innermost. + 11: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Rear gear number. 1 is innermost. name='rear_gear_num', type=BASE_TYPES[0x0A], # uint8z def_num=11, ), - 12: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Number of rear teeth. + 12: Field( # Do not populate directly. Autogenerated by decoder for gear_change subfield components. Number of rear teeth. name='rear_gear', type=BASE_TYPES[0x0A], # uint8z def_num=12, @@ -7013,6 +8868,57 @@ type=FIELD_TYPES['device_index'], def_num=13, ), + 14: Field( # Activity Type associated with an auto_activity_detect event + name='activity_type', + type=FIELD_TYPES['activity_type'], + def_num=14, + ), + 15: Field( # Timestamp of when the event started + name='start_timestamp', + type=FIELD_TYPES['date_time'], + def_num=15, + units='s', + subfields=( + SubField( # Auto Activity Detect Start Timestamp. + name='auto_activity_detect_start_timestamp', + def_num=15, + type=FIELD_TYPES['date_time'], + units='s', + ref_fields=( + ReferenceField( + name='event', + def_num=0, + value='auto_activity_detect', + raw_value=54, + ), + ), + ), + ), + ), + 21: Field( # Do not populate directly. Autogenerated by decoder for threat_alert subfield components. + name='radar_threat_level_max', + type=FIELD_TYPES['radar_threat_level_type'], + def_num=21, + ), + 22: Field( # Do not populate directly. Autogenerated by decoder for threat_alert subfield components. + name='radar_threat_count', + type=BASE_TYPES[0x02], # uint8 + def_num=22, + ), + 23: Field( # Do not populate directly. Autogenerated by decoder for radar_threat_alert subfield components + name='radar_threat_avg_approach_speed', + type=BASE_TYPES[0x02], # uint8 + def_num=23, + scale=10, + units='m/s', + ), + 24: Field( # Do not populate directly. Autogenerated by decoder for radar_threat_alert subfield components + name='radar_threat_max_approach_speed', + type=BASE_TYPES[0x02], # uint8 + def_num=24, + scale=10, + units='m/s', + ), 253: FIELD_TYPE_TIMESTAMP, }, ), @@ -7056,6 +8962,32 @@ ), ), ), + SubField( + name='ble_device_type', + def_num=1, + type=FIELD_TYPES['ble_device_type'], + ref_fields=( + ReferenceField( + name='source_type', + def_num=25, + value='bluetooth_low_energy', + raw_value=3, + ), + ), + ), + SubField( + name='local_device_type', + def_num=1, + type=FIELD_TYPES['local_device_type'], + ref_fields=( + ReferenceField( + name='source_type', + def_num=25, + value='local', + raw_value=5, + ), + ), + ), ), ), 2: Field( @@ -7073,6 +9005,19 @@ type=BASE_TYPES[0x84], # uint16 def_num=4, subfields=( + SubField( + name='favero_product', + def_num=4, + type=FIELD_TYPES['favero_product'], + ref_fields=( + ReferenceField( + name='manufacturer', + def_num=2, + value='favero_electronics', + raw_value=263, + ), + ), + ), SubField( name='garmin_product', def_num=4, @@ -7096,18 +9041,11 @@ value='dynastream_oem', raw_value=13, ), - ), - ), - SubField( - name='strava_product', - def_num=4, - type=FIELD_TYPES['strava_product'], - ref_fields=( ReferenceField( name='manufacturer', def_num=2, - value='strava', - raw_value=265, + value='tacx', + raw_value=89, ), ), ), @@ -7177,527 +9115,276 @@ type=BASE_TYPES[0x07], # string def_num=27, ), + 32: Field( + name='battery_level', + type=BASE_TYPES[0x02], # uint8 + def_num=32, + units='%', + ), 253: FIELD_TYPE_TIMESTAMP, }, ), - 27: MessageType( - name='workout_step', - mesg_num=27, + 34: MessageType( + name='activity', + mesg_num=34, fields={ - 0: Field( - name='wkt_step_name', - type=BASE_TYPES[0x07], # string + 0: Field( # Exclude pauses + name='total_timer_time', + type=BASE_TYPES[0x86], # uint32 def_num=0, + scale=1000, + units='s', ), 1: Field( - name='duration_type', - type=FIELD_TYPES['wkt_step_duration'], + name='num_sessions', + type=BASE_TYPES[0x84], # uint16 def_num=1, ), 2: Field( - name='duration_value', - type=BASE_TYPES[0x86], # uint32 + name='type', + type=FIELD_TYPES['activity'], def_num=2, - subfields=( - SubField( - name='duration_calories', - def_num=2, - type=BASE_TYPES[0x86], # uint32 - units='calories', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='calories', - raw_value=4, - ), - ), - ), - SubField( - name='duration_distance', - def_num=2, - type=BASE_TYPES[0x86], # uint32 - scale=100, - units='m', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='distance', - raw_value=1, - ), - ), - ), + ), + 3: Field( + name='event', + type=FIELD_TYPES['event'], + def_num=3, + ), + 4: Field( + name='event_type', + type=FIELD_TYPES['event_type'], + def_num=4, + ), + 5: Field( # timestamp epoch expressed in local time, used to convert activity timestamps to local time + name='local_timestamp', + type=FIELD_TYPES['local_date_time'], + def_num=5, + ), + 6: Field( + name='event_group', + type=BASE_TYPES[0x02], # uint8 + def_num=6, + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 72: MessageType( # Corresponds to file_id of workout or course. + name='training_file', + mesg_num=72, + fields={ + 0: Field( + name='type', + type=FIELD_TYPES['file'], + def_num=0, + ), + 1: Field( + name='manufacturer', + type=FIELD_TYPES['manufacturer'], + def_num=1, + ), + 2: Field( + name='product', + type=BASE_TYPES[0x84], # uint16 + def_num=2, + subfields=( SubField( - name='duration_hr', + name='favero_product', def_num=2, - type=FIELD_TYPES['workout_hr'], - units='% or bpm', + type=FIELD_TYPES['favero_product'], ref_fields=( ReferenceField( - name='duration_type', - def_num=1, - value='hr_less_than', - raw_value=2, - ), - ReferenceField( - name='duration_type', + name='manufacturer', def_num=1, - value='hr_greater_than', - raw_value=3, + value='favero_electronics', + raw_value=263, ), ), ), SubField( - name='duration_power', + name='garmin_product', def_num=2, - type=FIELD_TYPES['workout_power'], - units='% or watts', + type=FIELD_TYPES['garmin_product'], ref_fields=( ReferenceField( - name='duration_type', + name='manufacturer', def_num=1, - value='power_less_than', - raw_value=14, + value='garmin', + raw_value=1, ), ReferenceField( - name='duration_type', + name='manufacturer', def_num=1, - value='power_greater_than', + value='dynastream', raw_value=15, ), - ), - ), - SubField( - name='duration_reps', - def_num=2, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='reps', - raw_value=29, - ), - ), - ), - SubField( # message_index of step to loop back to. Steps are assumed to be in the order by message_index. custom_name and intensity members are undefined for this duration type. - name='duration_step', - def_num=2, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_steps_cmplt', - raw_value=6, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_time', - raw_value=7, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_distance', - raw_value=8, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_calories', - raw_value=9, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_hr_less_than', - raw_value=10, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_hr_greater_than', - raw_value=11, - ), ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_power_less_than', - raw_value=12, - ), - ReferenceField( - name='duration_type', + name='manufacturer', def_num=1, - value='repeat_until_power_greater_than', + value='dynastream_oem', raw_value=13, ), - ), - ), - SubField( - name='duration_time', - def_num=2, - type=BASE_TYPES[0x86], # uint32 - scale=1000, - units='s', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='time', - raw_value=0, - ), ReferenceField( - name='duration_type', + name='manufacturer', def_num=1, - value='repetition_time', - raw_value=28, + value='tacx', + raw_value=89, ), ), ), ), ), 3: Field( - name='target_type', - type=FIELD_TYPES['wkt_step_target'], + name='serial_number', + type=BASE_TYPES[0x8C], # uint32z def_num=3, ), 4: Field( - name='target_value', + name='time_created', + type=FIELD_TYPES['date_time'], + def_num=4, + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 101: MessageType( + name='length', + mesg_num=101, + fields={ + 0: Field( + name='event', + type=FIELD_TYPES['event'], + def_num=0, + ), + 1: Field( + name='event_type', + type=FIELD_TYPES['event_type'], + def_num=1, + ), + 2: Field( + name='start_time', + type=FIELD_TYPES['date_time'], + def_num=2, + ), + 3: Field( + name='total_elapsed_time', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + scale=1000, + units='s', + ), + 4: Field( + name='total_timer_time', type=BASE_TYPES[0x86], # uint32 def_num=4, - subfields=( - SubField( - name='repeat_calories', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - units='calories', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_calories', - raw_value=9, - ), - ), - ), - SubField( - name='repeat_distance', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - scale=100, - units='m', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_distance', - raw_value=8, - ), - ), - ), - SubField( - name='repeat_hr', - def_num=4, - type=FIELD_TYPES['workout_hr'], - units='% or bpm', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_hr_less_than', - raw_value=10, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_hr_greater_than', - raw_value=11, - ), - ), - ), - SubField( - name='repeat_power', - def_num=4, - type=FIELD_TYPES['workout_power'], - units='% or watts', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_power_less_than', - raw_value=12, - ), - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_power_greater_than', - raw_value=13, - ), - ), - ), - SubField( # # of repetitions - name='repeat_steps', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_steps_cmplt', - raw_value=6, - ), - ), - ), - SubField( - name='repeat_time', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - scale=1000, - units='s', - ref_fields=( - ReferenceField( - name='duration_type', - def_num=1, - value='repeat_until_time', - raw_value=7, - ), - ), - ), - SubField( # Zone (1-?); Custom = 0; - name='target_cadence_zone', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='cadence', - raw_value=3, - ), - ), - ), - SubField( # hr zone (1-5);Custom =0; - name='target_hr_zone', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='heart_rate', - raw_value=1, - ), - ), - ), - SubField( # Power Zone ( 1-7); Custom = 0; - name='target_power_zone', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='power', - raw_value=4, - ), - ), - ), - SubField( # speed zone (1-10);Custom =0; - name='target_speed_zone', - def_num=4, - type=BASE_TYPES[0x86], # uint32 - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='speed', - raw_value=0, - ), - ), - ), - SubField( - name='target_stroke_type', - def_num=4, - type=FIELD_TYPES['swim_stroke'], - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='swim_stroke', - raw_value=11, - ), - ), - ), - ), + scale=1000, + units='s', ), 5: Field( - name='custom_target_value_low', - type=BASE_TYPES[0x86], # uint32 + name='total_strokes', + type=BASE_TYPES[0x84], # uint16 def_num=5, - subfields=( - SubField( - name='custom_target_cadence_low', - def_num=5, - type=BASE_TYPES[0x86], # uint32 - units='rpm', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='cadence', - raw_value=3, - ), - ), - ), - SubField( - name='custom_target_heart_rate_low', - def_num=5, - type=FIELD_TYPES['workout_hr'], - units='% or bpm', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='heart_rate', - raw_value=1, - ), - ), - ), - SubField( - name='custom_target_power_low', - def_num=5, - type=FIELD_TYPES['workout_power'], - units='% or watts', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='power', - raw_value=4, - ), - ), - ), - SubField( - name='custom_target_speed_low', - def_num=5, - type=BASE_TYPES[0x86], # uint32 - scale=1000, - units='m/s', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='speed', - raw_value=0, - ), - ), - ), - ), + units='strokes', ), 6: Field( - name='custom_target_value_high', - type=BASE_TYPES[0x86], # uint32 + name='avg_speed', + type=BASE_TYPES[0x84], # uint16 def_num=6, - subfields=( - SubField( - name='custom_target_cadence_high', - def_num=6, - type=BASE_TYPES[0x86], # uint32 - units='rpm', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='cadence', - raw_value=3, - ), - ), - ), - SubField( - name='custom_target_heart_rate_high', - def_num=6, - type=FIELD_TYPES['workout_hr'], - units='% or bpm', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='heart_rate', - raw_value=1, - ), - ), - ), - SubField( - name='custom_target_power_high', - def_num=6, - type=FIELD_TYPES['workout_power'], - units='% or watts', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='power', - raw_value=4, - ), - ), - ), - SubField( - name='custom_target_speed_high', - def_num=6, - type=BASE_TYPES[0x86], # uint32 - scale=1000, - units='m/s', - ref_fields=( - ReferenceField( - name='target_type', - def_num=3, - value='speed', - raw_value=0, - ), - ), - ), - ), + scale=1000, + units='m/s', ), 7: Field( - name='intensity', - type=FIELD_TYPES['intensity'], + name='swim_stroke', + type=FIELD_TYPES['swim_stroke'], def_num=7, - ), - 8: Field( - name='notes', - type=BASE_TYPES[0x07], # string - def_num=8, + units='swim_stroke', ), 9: Field( - name='equipment', - type=FIELD_TYPES['workout_equipment'], + name='avg_swimming_cadence', + type=BASE_TYPES[0x02], # uint8 def_num=9, + units='strokes/min', ), 10: Field( - name='exercise_category', - type=FIELD_TYPES['exercise_category'], + name='event_group', + type=BASE_TYPES[0x02], # uint8 def_num=10, ), 11: Field( - name='exercise_name', + name='total_calories', type=BASE_TYPES[0x84], # uint16 def_num=11, + units='kcal', ), 12: Field( - name='exercise_weight', - type=BASE_TYPES[0x84], # uint16 + name='length_type', + type=FIELD_TYPES['length_type'], def_num=12, + ), + 18: Field( + name='player_score', + type=BASE_TYPES[0x84], # uint16 + def_num=18, + ), + 19: Field( + name='opponent_score', + type=BASE_TYPES[0x84], # uint16 + def_num=19, + ), + 20: Field( # stroke_type enum used as the index + name='stroke_count', + type=BASE_TYPES[0x84], # uint16 + def_num=20, + units='counts', + ), + 21: Field( # zone number used as the index + name='zone_count', + type=BASE_TYPES[0x84], # uint16 + def_num=21, + units='counts', + ), + 22: Field( + name='enhanced_avg_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=22, scale=100, - units='kg', + units='Breaths/min', ), - 13: Field( - name='weight_display_unit', - type=FIELD_TYPES['fit_base_unit'], - def_num=13, + 23: Field( + name='enhanced_max_respiration_rate', + type=BASE_TYPES[0x84], # uint16 + def_num=23, + scale=100, + units='Breaths/min', + ), + 24: Field( + name='avg_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=24, + components=( + ComponentField( + name='enhanced_avg_respiration_rate', + def_num=22, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), + ), + 25: Field( + name='max_respiration_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=25, + components=( + ComponentField( + name='enhanced_max_respiration_rate', + def_num=23, + accumulate=False, + bits=8, + bit_offset=0, + ), + ), ), + 253: FIELD_TYPE_TIMESTAMP, 254: Field( name='message_index', type=FIELD_TYPES['message_index'], @@ -7705,1924 +9392,1482 @@ ), }, ), - 32: MessageType( - name='course_point', - mesg_num=32, + 128: MessageType( + name='weather_conditions', + mesg_num=128, fields={ + 0: Field( # Current or forecast + name='weather_report', + type=FIELD_TYPES['weather_report'], + def_num=0, + ), 1: Field( - name='timestamp', - type=FIELD_TYPES['date_time'], + name='temperature', + type=BASE_TYPES[0x01], # sint8 def_num=1, + units='C', ), - 2: Field( - name='position_lat', - type=BASE_TYPES[0x85], # sint32 + 2: Field( # Corresponds to GSC Response weatherIcon field + name='condition', + type=FIELD_TYPES['weather_status'], def_num=2, - units='semicircles', ), 3: Field( - name='position_long', - type=BASE_TYPES[0x85], # sint32 + name='wind_direction', + type=BASE_TYPES[0x84], # uint16 def_num=3, - units='semicircles', + units='degrees', ), 4: Field( - name='distance', - type=BASE_TYPES[0x86], # uint32 + name='wind_speed', + type=BASE_TYPES[0x84], # uint16 def_num=4, - scale=100, - units='m', + scale=1000, + units='m/s', ), - 5: Field( - name='type', - type=FIELD_TYPES['course_point'], + 5: Field( # range 0-100 + name='precipitation_probability', + type=BASE_TYPES[0x02], # uint8 def_num=5, ), - 6: Field( - name='name', - type=BASE_TYPES[0x07], # string + 6: Field( # Heat Index if GCS heatIdx above or equal to 90F or wind chill if GCS windChill below or equal to 32F + name='temperature_feels_like', + type=BASE_TYPES[0x01], # sint8 def_num=6, + units='C', ), - 8: Field( - name='favorite', - type=FIELD_TYPES['bool'], + 7: Field( + name='relative_humidity', + type=BASE_TYPES[0x02], # uint8 + def_num=7, + ), + 8: Field( # string corresponding to GCS response location string + name='location', + type=BASE_TYPES[0x07], # string def_num=8, ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 9: Field( + name='observed_at_time', + type=FIELD_TYPES['date_time'], + def_num=9, + ), + 10: Field( + name='observed_location_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=10, + units='semicircles', + ), + 11: Field( + name='observed_location_long', + type=BASE_TYPES[0x85], # sint32 + def_num=11, + units='semicircles', ), + 12: Field( + name='day_of_week', + type=FIELD_TYPES['day_of_week'], + def_num=12, + ), + 13: Field( + name='high_temperature', + type=BASE_TYPES[0x01], # sint8 + def_num=13, + units='C', + ), + 14: Field( + name='low_temperature', + type=BASE_TYPES[0x01], # sint8 + def_num=14, + units='C', + ), + 253: FIELD_TYPE_TIMESTAMP, # time of update for current conditions, else forecast time }, ), - 37: MessageType( - name='file_capabilities', - mesg_num=37, + 129: MessageType( + name='weather_alert', + mesg_num=129, fields={ - 0: Field( - name='type', - type=FIELD_TYPES['file'], + 0: Field( # Unique identifier from GCS report ID string, length is 12 + name='report_id', + type=BASE_TYPES[0x07], # string def_num=0, ), - 1: Field( - name='flags', - type=FIELD_TYPES['file_flags'], + 1: Field( # Time alert was issued + name='issue_time', + type=FIELD_TYPES['date_time'], def_num=1, ), - 2: Field( - name='directory', - type=BASE_TYPES[0x07], # string + 2: Field( # Time alert expires + name='expire_time', + type=FIELD_TYPES['date_time'], def_num=2, ), - 3: Field( - name='max_count', - type=BASE_TYPES[0x84], # uint16 + 3: Field( # Warning, Watch, Advisory, Statement + name='severity', + type=FIELD_TYPES['weather_severity'], def_num=3, ), - 4: Field( - name='max_size', - type=BASE_TYPES[0x86], # uint32 + 4: Field( # Tornado, Severe Thunderstorm, etc. + name='type', + type=FIELD_TYPES['weather_severe_type'], def_num=4, - units='bytes', - ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 38: MessageType( - name='mesg_capabilities', - mesg_num=38, + 160: MessageType( + name='gps_metadata', + mesg_num=160, fields={ - 0: Field( - name='file', - type=FIELD_TYPES['file'], + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='ms', ), 1: Field( - name='mesg_num', - type=FIELD_TYPES['mesg_num'], + name='position_lat', + type=BASE_TYPES[0x85], # sint32 def_num=1, + units='semicircles', ), 2: Field( - name='count_type', - type=FIELD_TYPES['mesg_count'], + name='position_long', + type=BASE_TYPES[0x85], # sint32 def_num=2, + units='semicircles', ), 3: Field( - name='count', - type=BASE_TYPES[0x84], # uint16 + name='enhanced_altitude', + type=BASE_TYPES[0x86], # uint32 def_num=3, - subfields=( - SubField( - name='max_per_file', - def_num=3, - type=BASE_TYPES[0x84], # uint16 - ref_fields=( - ReferenceField( - name='count_type', - def_num=2, - value='max_per_file', - raw_value=1, - ), - ), - ), - SubField( - name='max_per_file_type', - def_num=3, - type=BASE_TYPES[0x84], # uint16 - ref_fields=( - ReferenceField( - name='count_type', - def_num=2, - value='max_per_file_type', - raw_value=2, - ), - ), - ), - SubField( - name='num_per_file', - def_num=3, - type=BASE_TYPES[0x84], # uint16 - ref_fields=( - ReferenceField( - name='count_type', - def_num=2, - value='num_per_file', - raw_value=0, - ), - ), - ), - ), + scale=5, + offset=500, + units='m', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 4: Field( + name='enhanced_speed', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + scale=1000, + units='m/s', + ), + 5: Field( + name='heading', + type=BASE_TYPES[0x84], # uint16 + def_num=5, + scale=100, + units='degrees', + ), + 6: Field( # Used to correlate UTC to system time if the timestamp of the message is in system time. This UTC time is derived from the GPS data. + name='utc_timestamp', + type=FIELD_TYPES['date_time'], + def_num=6, + units='s', + ), + 7: Field( # velocity[0] is lon velocity. Velocity[1] is lat velocity. Velocity[2] is altitude velocity. + name='velocity', + type=BASE_TYPES[0x83], # sint16 + def_num=7, + scale=100, + units='m/s', ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp. }, ), - 39: MessageType( - name='field_capabilities', - mesg_num=39, + 161: MessageType( + name='camera_event', + mesg_num=161, fields={ - 0: Field( - name='file', - type=FIELD_TYPES['file'], + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='ms', ), 1: Field( - name='mesg_num', - type=FIELD_TYPES['mesg_num'], + name='camera_event_type', + type=FIELD_TYPES['camera_event_type'], def_num=1, ), 2: Field( - name='field_num', - type=BASE_TYPES[0x02], # uint8 + name='camera_file_uuid', + type=BASE_TYPES[0x07], # string def_num=2, ), 3: Field( - name='count', - type=BASE_TYPES[0x84], # uint16 + name='camera_orientation', + type=FIELD_TYPES['camera_orientation_type'], def_num=3, ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, - ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp. }, ), - 49: MessageType( - name='file_creator', - mesg_num=49, + 164: MessageType( + name='gyroscope_data', + mesg_num=164, fields={ - 0: Field( - name='software_version', + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', type=BASE_TYPES[0x84], # uint16 def_num=0, + units='ms', ), - 1: Field( - name='hardware_version', - type=BASE_TYPES[0x02], # uint8 + 1: Field( # Each time in the array describes the time at which the gyro sample with the corrosponding index was taken. Limited to 30 samples in each message. The samples may span across seconds. Array size must match the number of samples in gyro_x and gyro_y and gyro_z + name='sample_time_offset', + type=BASE_TYPES[0x84], # uint16 def_num=1, + units='ms', ), - }, - ), - 53: MessageType( - name='speed_zone', - mesg_num=53, - fields={ - 0: Field( - name='high_value', + 2: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='gyro_x', type=BASE_TYPES[0x84], # uint16 - def_num=0, - scale=1000, - units='m/s', + def_num=2, + units='counts', ), - 1: Field( - name='name', - type=BASE_TYPES[0x07], # string - def_num=1, + 3: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='gyro_y', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + units='counts', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 4: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='gyro_z', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + units='counts', + ), + 5: Field( # Calibrated gyro reading + name='calibrated_gyro_x', + type=BASE_TYPES[0x88], # float32 + def_num=5, + units='deg/s', + ), + 6: Field( # Calibrated gyro reading + name='calibrated_gyro_y', + type=BASE_TYPES[0x88], # float32 + def_num=6, + units='deg/s', + ), + 7: Field( # Calibrated gyro reading + name='calibrated_gyro_z', + type=BASE_TYPES[0x88], # float32 + def_num=7, + units='deg/s', ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 55: MessageType( - name='monitoring', - mesg_num=55, + 165: MessageType( + name='accelerometer_data', + mesg_num=165, fields={ - 0: Field( # Associates this data to device_info message. Not required for file with single device (sensor). - name='device_index', - type=FIELD_TYPES['device_index'], + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='ms', ), - 1: Field( # Accumulated total calories. Maintained by MonitoringReader for each activity_type. See SDK documentation - name='calories', + 1: Field( # Each time in the array describes the time at which the accelerometer sample with the corrosponding index was taken. Limited to 30 samples in each message. The samples may span across seconds. Array size must match the number of samples in accel_x and accel_y and accel_z + name='sample_time_offset', type=BASE_TYPES[0x84], # uint16 def_num=1, - units='kcal', + units='ms', ), - 2: Field( # Accumulated distance. Maintained by MonitoringReader for each activity_type. See SDK documentation. - name='distance', - type=BASE_TYPES[0x86], # uint32 + 2: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='accel_x', + type=BASE_TYPES[0x84], # uint16 def_num=2, - scale=100, - units='m', + units='counts', ), - 3: Field( # Accumulated cycles. Maintained by MonitoringReader for each activity_type. See SDK documentation. - name='cycles', - type=BASE_TYPES[0x86], # uint32 + 3: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='accel_y', + type=BASE_TYPES[0x84], # uint16 def_num=3, - scale=2, - units='cycles', - subfields=( - SubField( - name='steps', - def_num=3, - type=BASE_TYPES[0x86], # uint32 - units='steps', - ref_fields=( - ReferenceField( - name='activity_type', - def_num=5, - value='walking', - raw_value=6, - ), - ReferenceField( - name='activity_type', - def_num=5, - value='running', - raw_value=1, - ), - ), - ), - SubField( - name='strokes', - def_num=3, - type=BASE_TYPES[0x86], # uint32 - scale=2, - units='strokes', - ref_fields=( - ReferenceField( - name='activity_type', - def_num=5, - value='cycling', - raw_value=2, - ), - ReferenceField( - name='activity_type', - def_num=5, - value='swimming', - raw_value=5, - ), - ), - ), - ), + units='counts', ), - 4: Field( - name='active_time', - type=BASE_TYPES[0x86], # uint32 + 4: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='accel_z', + type=BASE_TYPES[0x84], # uint16 def_num=4, - scale=1000, - units='s', - ), - 5: Field( - name='activity_type', - type=FIELD_TYPES['activity_type'], - def_num=5, + units='counts', ), - 6: Field( - name='activity_subtype', - type=FIELD_TYPES['activity_subtype'], + 5: Field( # Calibrated accel reading + name='calibrated_accel_x', + type=BASE_TYPES[0x88], # float32 + def_num=5, + units='g', + ), + 6: Field( # Calibrated accel reading + name='calibrated_accel_y', + type=BASE_TYPES[0x88], # float32 def_num=6, + units='g', ), - 7: Field( - name='activity_level', - type=FIELD_TYPES['activity_level'], + 7: Field( # Calibrated accel reading + name='calibrated_accel_z', + type=BASE_TYPES[0x88], # float32 def_num=7, + units='g', ), - 8: Field( - name='distance_16', - type=BASE_TYPES[0x84], # uint16 - def_num=8, - units='100*m', - ), - 9: Field( - name='cycles_16', - type=BASE_TYPES[0x84], # uint16 - def_num=9, - units='2*cycles or steps', - ), - 10: Field( - name='active_time_16', - type=BASE_TYPES[0x84], # uint16 - def_num=10, - units='s', - ), - 11: Field( # Must align to logging interval, for example, time must be 00:00:00 for daily log. - name='local_timestamp', - type=FIELD_TYPES['local_date_time'], - def_num=11, - ), - 12: Field( # Avg temperature during the logging interval ended at timestamp - name='temperature', + 8: Field( # Calibrated accel reading + name='compressed_calibrated_accel_x', type=BASE_TYPES[0x83], # sint16 - def_num=12, - scale=100, - units='C', + def_num=8, + units='mG', ), - 14: Field( # Min temperature during the logging interval ended at timestamp - name='temperature_min', + 9: Field( # Calibrated accel reading + name='compressed_calibrated_accel_y', type=BASE_TYPES[0x83], # sint16 - def_num=14, - scale=100, - units='C', + def_num=9, + units='mG', ), - 15: Field( # Max temperature during the logging interval ended at timestamp - name='temperature_max', + 10: Field( # Calibrated accel reading + name='compressed_calibrated_accel_z', type=BASE_TYPES[0x83], # sint16 - def_num=15, - scale=100, - units='C', - ), - 16: Field( # Indexed using minute_activity_level enum - name='activity_time', - type=BASE_TYPES[0x84], # uint16 - def_num=16, - units='minutes', - ), - 19: Field( - name='active_calories', - type=BASE_TYPES[0x84], # uint16 - def_num=19, - units='kcal', - ), - 24: Field( # Indicates single type / intensity for duration since last monitoring message. - name='current_activity_type_intensity', - type=BASE_TYPES[0x0D], # byte - def_num=24, - components=( - ComponentField( - name='activity_type', - def_num=5, - accumulate=False, - bits=5, - bit_offset=0, - ), - ComponentField( - name='intensity', - def_num=28, - accumulate=False, - bits=3, - bit_offset=5, - ), - ), - ), - 25: Field( - name='timestamp_min_8', - type=BASE_TYPES[0x02], # uint8 - def_num=25, - units='min', - ), - 26: Field( - name='timestamp_16', - type=BASE_TYPES[0x84], # uint16 - def_num=26, - units='s', - ), - 27: Field( - name='heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=27, - units='bpm', - ), - 28: Field( - name='intensity', - type=BASE_TYPES[0x02], # uint8 - def_num=28, - scale=10, - ), - 29: Field( - name='duration_min', - type=BASE_TYPES[0x84], # uint16 - def_num=29, - units='min', - ), - 30: Field( - name='duration', - type=BASE_TYPES[0x86], # uint32 - def_num=30, - units='s', - ), - 31: Field( - name='ascent', - type=BASE_TYPES[0x86], # uint32 - def_num=31, - scale=1000, - units='m', - ), - 32: Field( - name='descent', - type=BASE_TYPES[0x86], # uint32 - def_num=32, - scale=1000, - units='m', - ), - 33: Field( - name='moderate_activity_minutes', - type=BASE_TYPES[0x84], # uint16 - def_num=33, - units='minutes', - ), - 34: Field( - name='vigorous_activity_minutes', - type=BASE_TYPES[0x84], # uint16 - def_num=34, - units='minutes', + def_num=10, + units='mG', ), - 253: FIELD_TYPE_TIMESTAMP, # Must align to logging interval, for example, time must be 00:00:00 for daily log. + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 72: MessageType( # Corresponds to file_id of workout or course. - name='training_file', - mesg_num=72, + 167: MessageType( + name='three_d_sensor_calibration', + mesg_num=167, fields={ - 0: Field( - name='type', - type=FIELD_TYPES['file'], + 0: Field( # Indicates which sensor the calibration is for + name='sensor_type', + type=FIELD_TYPES['sensor_type'], def_num=0, ), - 1: Field( - name='manufacturer', - type=FIELD_TYPES['manufacturer'], + 1: Field( # Calibration factor used to convert from raw ADC value to degrees, g, etc. + name='calibration_factor', + type=BASE_TYPES[0x86], # uint32 def_num=1, - ), - 2: Field( - name='product', - type=BASE_TYPES[0x84], # uint16 - def_num=2, subfields=( - SubField( - name='garmin_product', - def_num=2, - type=FIELD_TYPES['garmin_product'], + SubField( # Accelerometer calibration factor + name='accel_cal_factor', + def_num=1, + type=BASE_TYPES[0x86], # uint32 + units='g', ref_fields=( ReferenceField( - name='manufacturer', - def_num=1, - value='garmin', - raw_value=1, - ), - ReferenceField( - name='manufacturer', - def_num=1, - value='dynastream', - raw_value=15, + name='sensor_type', + def_num=0, + value='accelerometer', + raw_value=0, ), + ), + ), + SubField( # Gyro calibration factor + name='gyro_cal_factor', + def_num=1, + type=BASE_TYPES[0x86], # uint32 + units='deg/s', + ref_fields=( ReferenceField( - name='manufacturer', - def_num=1, - value='dynastream_oem', - raw_value=13, + name='sensor_type', + def_num=0, + value='gyroscope', + raw_value=1, ), ), ), ), ), - 3: Field( - name='serial_number', - type=BASE_TYPES[0x8C], # uint32z + 2: Field( # Calibration factor divisor + name='calibration_divisor', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + units='counts', + ), + 3: Field( # Level shift value used to shift the ADC value back into range + name='level_shift', + type=BASE_TYPES[0x86], # uint32 def_num=3, ), - 4: Field( - name='time_created', - type=FIELD_TYPES['date_time'], + 4: Field( # Internal calibration factors, one for each: xy, yx, zx + name='offset_cal', + type=BASE_TYPES[0x85], # sint32 def_num=4, ), - 253: FIELD_TYPE_TIMESTAMP, + 5: Field( # 3 x 3 rotation matrix (row major) + name='orientation_matrix', + type=BASE_TYPES[0x85], # sint32 + def_num=5, + scale=65535, + ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 78: MessageType( # Heart rate variability - name='hrv', - mesg_num=78, + 169: MessageType( + name='video_frame', + mesg_num=169, fields={ - 0: Field( # Time between beats - name='time', + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', type=BASE_TYPES[0x84], # uint16 def_num=0, - scale=1000, - units='s', + units='ms', + ), + 1: Field( # Number of the frame that the timestamp and timestamp_ms correlate to + name='frame_number', + type=BASE_TYPES[0x86], # uint32 + def_num=1, ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 80: MessageType( - name='ant_rx', - mesg_num=80, + 174: MessageType( + name='obdii_data', + mesg_num=174, fields={ - 0: Field( - name='fractional_timestamp', + 0: Field( # Fractional part of timestamp, added to timestamp + name='timestamp_ms', type=BASE_TYPES[0x84], # uint16 def_num=0, - scale=32768, - units='s', + units='ms', ), - 1: Field( - name='mesg_id', - type=BASE_TYPES[0x0D], # byte + 1: Field( # Offset of PID reading [i] from start_timestamp+start_timestamp_ms. Readings may span accross seconds. + name='time_offset', + type=BASE_TYPES[0x84], # uint16 def_num=1, + units='ms', ), - 2: Field( - name='mesg_data', + 2: Field( # Parameter ID + name='pid', type=BASE_TYPES[0x0D], # byte def_num=2, - components=( - ComponentField( - name='channel_number', - def_num=3, - accumulate=False, - bits=8, - bit_offset=0, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=8, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=16, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=24, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=32, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=40, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=48, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=56, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=64, - ), - ), ), - 3: Field( - name='channel_number', - type=BASE_TYPES[0x02], # uint8 + 3: Field( # Raw parameter data + name='raw_data', + type=BASE_TYPES[0x0D], # byte def_num=3, ), - 4: Field( - name='data', - type=BASE_TYPES[0x0D], # byte + 4: Field( # Optional, data size of PID[i]. If not specified refer to SAE J1979. + name='pid_data_size', + type=BASE_TYPES[0x02], # uint8 def_num=4, ), - 253: FIELD_TYPE_TIMESTAMP, + 5: Field( # System time associated with sample expressed in ms, can be used instead of time_offset. There will be a system_time value for each raw_data element. For multibyte pids the system_time is repeated. + name='system_time', + type=BASE_TYPES[0x86], # uint32 + def_num=5, + ), + 6: Field( # Timestamp of first sample recorded in the message. Used with time_offset to generate time of each sample + name='start_timestamp', + type=FIELD_TYPES['date_time'], + def_num=6, + ), + 7: Field( # Fractional part of start_timestamp + name='start_timestamp_ms', + type=BASE_TYPES[0x84], # uint16 + def_num=7, + units='ms', + ), + 253: FIELD_TYPE_TIMESTAMP, # Timestamp message was output }, ), - 81: MessageType( - name='ant_tx', - mesg_num=81, + 177: MessageType( + name='nmea_sentence', + mesg_num=177, fields={ - 0: Field( - name='fractional_timestamp', + 0: Field( # Fractional part of timestamp, added to timestamp + name='timestamp_ms', type=BASE_TYPES[0x84], # uint16 def_num=0, - scale=32768, - units='s', + units='ms', ), - 1: Field( - name='mesg_id', - type=BASE_TYPES[0x0D], # byte + 1: Field( # NMEA sentence + name='sentence', + type=BASE_TYPES[0x07], # string def_num=1, ), - 2: Field( - name='mesg_data', - type=BASE_TYPES[0x0D], # byte - def_num=2, - components=( - ComponentField( - name='channel_number', - def_num=3, - accumulate=False, - bits=8, - bit_offset=0, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=8, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=16, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=24, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=32, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=40, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=48, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=56, - ), - ComponentField( - name='data', - def_num=4, - accumulate=False, - bits=8, - bit_offset=64, - ), - ), - ), - 3: Field( - name='channel_number', - type=BASE_TYPES[0x02], # uint8 - def_num=3, - ), - 4: Field( - name='data', - type=BASE_TYPES[0x0D], # byte - def_num=4, - ), - 253: FIELD_TYPE_TIMESTAMP, + 253: FIELD_TYPE_TIMESTAMP, # Timestamp message was output }, ), - 82: MessageType( - name='ant_channel_id', - mesg_num=82, + 178: MessageType( + name='aviation_attitude', + mesg_num=178, fields={ - 0: Field( - name='channel_number', - type=BASE_TYPES[0x02], # uint8 + 0: Field( # Fractional part of timestamp, added to timestamp + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='ms', ), - 1: Field( - name='device_type', - type=BASE_TYPES[0x0A], # uint8z + 1: Field( # System time associated with sample expressed in ms. + name='system_time', + type=BASE_TYPES[0x86], # uint32 def_num=1, + units='ms', ), - 2: Field( - name='device_number', - type=BASE_TYPES[0x8B], # uint16z - def_num=2, - ), - 3: Field( - name='transmission_type', - type=BASE_TYPES[0x0A], # uint8z - def_num=3, - ), - 4: Field( - name='device_index', - type=FIELD_TYPES['device_index'], - def_num=4, - ), - }, - ), - 101: MessageType( - name='length', - mesg_num=101, - fields={ - 0: Field( - name='event', - type=FIELD_TYPES['event'], - def_num=0, - ), - 1: Field( - name='event_type', - type=FIELD_TYPES['event_type'], - def_num=1, - ), - 2: Field( - name='start_time', - type=FIELD_TYPES['date_time'], + 2: Field( # Range -PI/2 to +PI/2 + name='pitch', + type=BASE_TYPES[0x83], # sint16 def_num=2, + scale=10430.38, + units='radians', ), - 3: Field( - name='total_elapsed_time', - type=BASE_TYPES[0x86], # uint32 + 3: Field( # Range -PI to +PI + name='roll', + type=BASE_TYPES[0x83], # sint16 def_num=3, - scale=1000, - units='s', + scale=10430.38, + units='radians', ), - 4: Field( - name='total_timer_time', - type=BASE_TYPES[0x86], # uint32 + 4: Field( # Range -78.4 to +78.4 (-8 Gs to 8 Gs) + name='accel_lateral', + type=BASE_TYPES[0x83], # sint16 def_num=4, - scale=1000, - units='s', + scale=100, + units='m/s^2', ), - 5: Field( - name='total_strokes', - type=BASE_TYPES[0x84], # uint16 + 5: Field( # Range -78.4 to +78.4 (-8 Gs to 8 Gs) + name='accel_normal', + type=BASE_TYPES[0x83], # sint16 def_num=5, - units='strokes', + scale=100, + units='m/s^2', ), - 6: Field( - name='avg_speed', - type=BASE_TYPES[0x84], # uint16 + 6: Field( # Range -8.727 to +8.727 (-500 degs/sec to +500 degs/sec) + name='turn_rate', + type=BASE_TYPES[0x83], # sint16 def_num=6, - scale=1000, - units='m/s', + scale=1024, + units='radians/second', ), 7: Field( - name='swim_stroke', - type=FIELD_TYPES['swim_stroke'], + name='stage', + type=FIELD_TYPES['attitude_stage'], def_num=7, - units='swim_stroke', ), - 9: Field( - name='avg_swimming_cadence', + 8: Field( # The percent complete of the current attitude stage. Set to 0 for attitude stages 0, 1 and 2 and to 100 for attitude stage 3 by AHRS modules that do not support it. Range - 100 + name='attitude_stage_complete', type=BASE_TYPES[0x02], # uint8 + def_num=8, + units='%', + ), + 9: Field( # Track Angle/Heading Range 0 - 2pi + name='track', + type=BASE_TYPES[0x84], # uint16 def_num=9, - units='strokes/min', + scale=10430.38, + units='radians', ), 10: Field( - name='event_group', - type=BASE_TYPES[0x02], # uint8 + name='validity', + type=FIELD_TYPES['attitude_validity'], def_num=10, ), - 11: Field( - name='total_calories', - type=BASE_TYPES[0x84], # uint16 - def_num=11, - units='kcal', - ), - 12: Field( - name='length_type', - type=FIELD_TYPES['length_type'], - def_num=12, + 253: FIELD_TYPE_TIMESTAMP, # Timestamp message was output + }, + ), + 184: MessageType( + name='video', + mesg_num=184, + fields={ + 0: Field( + name='url', + type=BASE_TYPES[0x07], # string + def_num=0, ), - 18: Field( - name='player_score', - type=BASE_TYPES[0x84], # uint16 - def_num=18, + 1: Field( + name='hosting_provider', + type=BASE_TYPES[0x07], # string + def_num=1, ), - 19: Field( - name='opponent_score', - type=BASE_TYPES[0x84], # uint16 - def_num=19, + 2: Field( # Playback time of video + name='duration', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + units='ms', ), - 20: Field( # stroke_type enum used as the index - name='stroke_count', + }, + ), + 185: MessageType( + name='video_title', + mesg_num=185, + fields={ + 0: Field( # Total number of title parts + name='message_count', type=BASE_TYPES[0x84], # uint16 - def_num=20, - units='counts', + def_num=0, ), - 21: Field( # zone number used as the index - name='zone_count', - type=BASE_TYPES[0x84], # uint16 - def_num=21, - units='counts', + 1: Field( + name='text', + type=BASE_TYPES[0x07], # string + def_num=1, ), - 253: FIELD_TYPE_TIMESTAMP, - 254: Field( + 254: Field( # Long titles will be split into multiple parts name='message_index', type=FIELD_TYPES['message_index'], def_num=254, ), }, ), - 106: MessageType( - name='slave_device', - mesg_num=106, + 186: MessageType( + name='video_description', + mesg_num=186, fields={ - 0: Field( - name='manufacturer', - type=FIELD_TYPES['manufacturer'], + 0: Field( # Total number of description parts + name='message_count', + type=BASE_TYPES[0x84], # uint16 def_num=0, ), 1: Field( - name='product', - type=BASE_TYPES[0x84], # uint16 + name='text', + type=BASE_TYPES[0x07], # string def_num=1, - subfields=( - SubField( - name='garmin_product', - def_num=1, - type=FIELD_TYPES['garmin_product'], - ref_fields=( - ReferenceField( - name='manufacturer', - def_num=0, - value='garmin', - raw_value=1, - ), - ReferenceField( - name='manufacturer', - def_num=0, - value='dynastream', - raw_value=15, - ), - ReferenceField( - name='manufacturer', - def_num=0, - value='dynastream_oem', - raw_value=13, - ), - ), - ), - SubField( - name='strava_product', - def_num=1, - type=FIELD_TYPES['strava_product'], - ref_fields=( - ReferenceField( - name='manufacturer', - def_num=0, - value='strava', - raw_value=265, - ), - ), - ), - ), + ), + 254: Field( # Long descriptions will be split into multiple parts + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, ), }, ), - 127: MessageType( - name='connectivity', - mesg_num=127, + 187: MessageType( + name='video_clip', + mesg_num=187, fields={ - 0: Field( # Use Bluetooth for connectivity features - name='bluetooth_enabled', - type=FIELD_TYPES['bool'], + 0: Field( + name='clip_number', + type=BASE_TYPES[0x84], # uint16 def_num=0, ), - 1: Field( # Use Bluetooth Low Energy for connectivity features - name='bluetooth_le_enabled', - type=FIELD_TYPES['bool'], + 1: Field( + name='start_timestamp', + type=FIELD_TYPES['date_time'], def_num=1, ), - 2: Field( # Use ANT for connectivity features - name='ant_enabled', - type=FIELD_TYPES['bool'], + 2: Field( + name='start_timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=2, ), 3: Field( - name='name', - type=BASE_TYPES[0x07], # string + name='end_timestamp', + type=FIELD_TYPES['date_time'], def_num=3, ), 4: Field( - name='live_tracking_enabled', - type=FIELD_TYPES['bool'], + name='end_timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=4, ), - 5: Field( - name='weather_conditions_enabled', - type=FIELD_TYPES['bool'], - def_num=5, - ), - 6: Field( - name='weather_alerts_enabled', - type=FIELD_TYPES['bool'], + 6: Field( # Start of clip in video time + name='clip_start', + type=BASE_TYPES[0x86], # uint32 def_num=6, + units='ms', ), - 7: Field( - name='auto_activity_upload_enabled', - type=FIELD_TYPES['bool'], + 7: Field( # End of clip in video time + name='clip_end', + type=BASE_TYPES[0x86], # uint32 def_num=7, - ), - 8: Field( - name='course_download_enabled', - type=FIELD_TYPES['bool'], - def_num=8, - ), - 9: Field( - name='workout_download_enabled', - type=FIELD_TYPES['bool'], - def_num=9, - ), - 10: Field( - name='gps_ephemeris_download_enabled', - type=FIELD_TYPES['bool'], - def_num=10, - ), - 11: Field( - name='incident_detection_enabled', - type=FIELD_TYPES['bool'], - def_num=11, - ), - 12: Field( - name='grouptrack_enabled', - type=FIELD_TYPES['bool'], - def_num=12, + units='ms', ), }, ), - 128: MessageType( - name='weather_conditions', - mesg_num=128, + 206: MessageType( # Must be logged before developer field is used + name='field_description', + mesg_num=206, fields={ - 0: Field( # Current or forecast - name='weather_report', - type=FIELD_TYPES['weather_report'], + 0: Field( + name='developer_data_index', + type=BASE_TYPES[0x02], # uint8 def_num=0, ), 1: Field( - name='temperature', - type=BASE_TYPES[0x01], # sint8 + name='field_definition_number', + type=BASE_TYPES[0x02], # uint8 def_num=1, - units='C', ), - 2: Field( # Corresponds to GSC Response weatherIcon field - name='condition', - type=FIELD_TYPES['weather_status'], + 2: Field( + name='fit_base_type_id', + type=FIELD_TYPES['fit_base_type'], def_num=2, ), 3: Field( - name='wind_direction', - type=BASE_TYPES[0x84], # uint16 + name='field_name', + type=BASE_TYPES[0x07], # string def_num=3, - units='degrees', ), 4: Field( - name='wind_speed', - type=BASE_TYPES[0x84], # uint16 + name='array', + type=BASE_TYPES[0x02], # uint8 def_num=4, - scale=1000, - units='m/s', ), - 5: Field( # range 0-100 - name='precipitation_probability', - type=BASE_TYPES[0x02], # uint8 + 5: Field( + name='components', + type=BASE_TYPES[0x07], # string def_num=5, ), - 6: Field( # Heat Index if GCS heatIdx above or equal to 90F or wind chill if GCS windChill below or equal to 32F - name='temperature_feels_like', - type=BASE_TYPES[0x01], # sint8 + 6: Field( + name='scale', + type=BASE_TYPES[0x02], # uint8 def_num=6, - units='C', ), 7: Field( - name='relative_humidity', - type=BASE_TYPES[0x02], # uint8 + name='offset', + type=BASE_TYPES[0x01], # sint8 def_num=7, ), - 8: Field( # string corresponding to GCS response location string - name='location', + 8: Field( + name='units', type=BASE_TYPES[0x07], # string def_num=8, ), 9: Field( - name='observed_at_time', - type=FIELD_TYPES['date_time'], + name='bits', + type=BASE_TYPES[0x07], # string def_num=9, ), 10: Field( - name='observed_location_lat', - type=BASE_TYPES[0x85], # sint32 + name='accumulate', + type=BASE_TYPES[0x07], # string def_num=10, - units='semicircles', - ), - 11: Field( - name='observed_location_long', - type=BASE_TYPES[0x85], # sint32 - def_num=11, - units='semicircles', - ), - 12: Field( - name='day_of_week', - type=FIELD_TYPES['day_of_week'], - def_num=12, ), 13: Field( - name='high_temperature', - type=BASE_TYPES[0x01], # sint8 + name='fit_base_unit_id', + type=FIELD_TYPES['fit_base_unit'], def_num=13, - units='C', ), 14: Field( - name='low_temperature', - type=BASE_TYPES[0x01], # sint8 + name='native_mesg_num', + type=FIELD_TYPES['mesg_num'], def_num=14, - units='C', ), - 253: FIELD_TYPE_TIMESTAMP, # time of update for current conditions, else forecast time + 15: Field( + name='native_field_num', + type=BASE_TYPES[0x02], # uint8 + def_num=15, + ), }, ), - 129: MessageType( - name='weather_alert', - mesg_num=129, + 207: MessageType( # Must be logged before field description + name='developer_data_id', + mesg_num=207, fields={ - 0: Field( # Unique identifier from GCS report ID string, length is 12 - name='report_id', - type=BASE_TYPES[0x07], # string + 0: Field( + name='developer_id', + type=BASE_TYPES[0x0D], # byte def_num=0, ), - 1: Field( # Time alert was issued - name='issue_time', - type=FIELD_TYPES['date_time'], + 1: Field( + name='application_id', + type=BASE_TYPES[0x0D], # byte def_num=1, ), - 2: Field( # Time alert expires - name='expire_time', - type=FIELD_TYPES['date_time'], + 2: Field( + name='manufacturer_id', + type=FIELD_TYPES['manufacturer'], def_num=2, ), - 3: Field( # Warning, Watch, Advisory, Statement - name='severity', - type=FIELD_TYPES['weather_severity'], + 3: Field( + name='developer_data_index', + type=BASE_TYPES[0x02], # uint8 def_num=3, ), - 4: Field( # Tornado, Severe Thunderstorm, etc. - name='type', - type=FIELD_TYPES['weather_severe_type'], + 4: Field( + name='application_version', + type=BASE_TYPES[0x86], # uint32 def_num=4, ), - 253: FIELD_TYPE_TIMESTAMP, }, ), - 131: MessageType( - name='cadence_zone', - mesg_num=131, + 208: MessageType( + name='magnetometer_data', + mesg_num=208, fields={ - 0: Field( - name='high_value', - type=BASE_TYPES[0x02], # uint8 + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 def_num=0, - units='rpm', + units='ms', ), - 1: Field( - name='name', - type=BASE_TYPES[0x07], # string + 1: Field( # Each time in the array describes the time at which the compass sample with the corrosponding index was taken. Limited to 30 samples in each message. The samples may span across seconds. Array size must match the number of samples in cmps_x and cmps_y and cmps_z + name='sample_time_offset', + type=BASE_TYPES[0x84], # uint16 def_num=1, + units='ms', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 2: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='mag_x', + type=BASE_TYPES[0x84], # uint16 + def_num=2, + units='counts', + ), + 3: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='mag_y', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + units='counts', + ), + 4: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. + name='mag_z', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + units='counts', + ), + 5: Field( # Calibrated Magnetometer reading + name='calibrated_mag_x', + type=BASE_TYPES[0x88], # float32 + def_num=5, + units='G', + ), + 6: Field( # Calibrated Magnetometer reading + name='calibrated_mag_y', + type=BASE_TYPES[0x88], # float32 + def_num=6, + units='G', + ), + 7: Field( # Calibrated Magnetometer reading + name='calibrated_mag_z', + type=BASE_TYPES[0x88], # float32 + def_num=7, + units='G', ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 132: MessageType( - name='hr', - mesg_num=132, + 209: MessageType( + name='barometer_data', + mesg_num=209, fields={ - 0: Field( - name='fractional_timestamp', + 0: Field( # Millisecond part of the timestamp. + name='timestamp_ms', type=BASE_TYPES[0x84], # uint16 def_num=0, - scale=32768, - units='s', + units='ms', ), - 1: Field( - name='time256', - type=BASE_TYPES[0x02], # uint8 + 1: Field( # Each time in the array describes the time at which the barometer sample with the corrosponding index was taken. The samples may span across seconds. Array size must match the number of samples in baro_cal + name='sample_time_offset', + type=BASE_TYPES[0x84], # uint16 def_num=1, - scale=256, - units='s', - components=( - ComponentField( - name='fractional_timestamp', - def_num=0, - scale=256, - units='s', - accumulate=False, - bits=8, - bit_offset=0, - ), + units='ms', + ), + 2: Field( # These are the raw ADC reading. The samples may span across seconds. A conversion will need to be done on this data once read. + name='baro_pres', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + units='Pa', + ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp + }, + ), + 210: MessageType( + name='one_d_sensor_calibration', + mesg_num=210, + fields={ + 0: Field( # Indicates which sensor the calibration is for + name='sensor_type', + type=FIELD_TYPES['sensor_type'], + def_num=0, + ), + 1: Field( # Calibration factor used to convert from raw ADC value to degrees, g, etc. + name='calibration_factor', + type=BASE_TYPES[0x86], # uint32 + def_num=1, + subfields=( + SubField( # Barometer calibration factor + name='baro_cal_factor', + def_num=1, + type=BASE_TYPES[0x86], # uint32 + units='Pa', + ref_fields=( + ReferenceField( + name='sensor_type', + def_num=0, + value='barometer', + raw_value=3, + ), + ), + ), ), ), - 6: Field( - name='filtered_bpm', - type=BASE_TYPES[0x02], # uint8 + 2: Field( # Calibration factor divisor + name='calibration_divisor', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + units='counts', + ), + 3: Field( # Level shift value used to shift the ADC value back into range + name='level_shift', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + ), + 4: Field( # Internal Calibration factor + name='offset_cal', + type=BASE_TYPES[0x85], # sint32 + def_num=4, + ), + 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp + }, + ), + 225: MessageType( + name='set', + mesg_num=225, + fields={ + 0: Field( + name='duration', + type=BASE_TYPES[0x86], # uint32 + def_num=0, + scale=1000, + units='s', + ), + 3: Field( # # of repitions of the movement + name='repetitions', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + ), + 4: Field( # Amount of weight applied for the set + name='weight', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + scale=16, + units='kg', + ), + 5: Field( + name='set_type', + type=FIELD_TYPES['set_type'], + def_num=5, + ), + 6: Field( # Start time of the set + name='start_time', + type=FIELD_TYPES['date_time'], def_num=6, - units='bpm', + ), + 7: Field( + name='category', + type=FIELD_TYPES['exercise_category'], + def_num=7, + ), + 8: Field( # Based on the associated category, see [category]_exercise_names + name='category_subtype', + type=BASE_TYPES[0x84], # uint16 + def_num=8, ), 9: Field( - name='event_timestamp', - type=BASE_TYPES[0x86], # uint32 + name='weight_display_unit', + type=FIELD_TYPES['fit_base_unit'], def_num=9, - scale=1024, - units='s', ), 10: Field( - name='event_timestamp_12', - type=BASE_TYPES[0x0D], # byte + name='message_index', + type=FIELD_TYPES['message_index'], def_num=10, - components=( - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=0, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=12, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=24, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=36, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=48, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=60, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=72, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=84, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=96, - ), - ComponentField( - name='event_timestamp', - def_num=9, - scale=1024, - units='s', - accumulate=True, - bits=12, - bit_offset=108, - ), - ), ), - 253: FIELD_TYPE_TIMESTAMP, + 11: Field( + name='wkt_step_index', + type=FIELD_TYPES['message_index'], + def_num=11, + ), + 254: Field( # Timestamp of the set + name='timestamp', + type=FIELD_TYPES['date_time'], + def_num=254, + ), }, ), - 142: MessageType( - name='segment_lap', - mesg_num=142, + 285: MessageType( + name='jump', + mesg_num=285, fields={ 0: Field( - name='event', - type=FIELD_TYPES['event'], + name='distance', + type=BASE_TYPES[0x88], # float32 def_num=0, + units='m', ), 1: Field( - name='event_type', - type=FIELD_TYPES['event_type'], + name='height', + type=BASE_TYPES[0x88], # float32 def_num=1, + units='m', ), 2: Field( - name='start_time', - type=FIELD_TYPES['date_time'], + name='rotations', + type=BASE_TYPES[0x02], # uint8 def_num=2, ), 3: Field( - name='start_position_lat', - type=BASE_TYPES[0x85], # sint32 + name='hang_time', + type=BASE_TYPES[0x88], # float32 def_num=3, - units='semicircles', + units='s', ), - 4: Field( - name='start_position_long', - type=BASE_TYPES[0x85], # sint32 + 4: Field( # A score for a jump calculated based on hang time, rotations, and distance. + name='score', + type=BASE_TYPES[0x88], # float32 def_num=4, - units='semicircles', ), 5: Field( - name='end_position_lat', + name='position_lat', type=BASE_TYPES[0x85], # sint32 def_num=5, units='semicircles', ), 6: Field( - name='end_position_long', + name='position_long', type=BASE_TYPES[0x85], # sint32 def_num=6, units='semicircles', ), - 7: Field( # Time (includes pauses) - name='total_elapsed_time', - type=BASE_TYPES[0x86], # uint32 + 7: Field( + name='speed', + type=BASE_TYPES[0x84], # uint16 def_num=7, scale=1000, - units='s', - ), - 8: Field( # Timer Time (excludes pauses) - name='total_timer_time', + units='m/s', + components=( + ComponentField( + name='enhanced_speed', + def_num=8, + scale=1000, + units='m/s', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), + ), + 8: Field( + name='enhanced_speed', type=BASE_TYPES[0x86], # uint32 def_num=8, scale=1000, + units='m/s', + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 312: MessageType( + name='split', + mesg_num=312, + fields={ + 0: Field( + name='split_type', + type=FIELD_TYPES['split_type'], + def_num=0, + ), + 1: Field( + name='total_elapsed_time', + type=BASE_TYPES[0x86], # uint32 + def_num=1, + scale=1000, units='s', ), - 9: Field( + 2: Field( + name='total_timer_time', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + scale=1000, + units='s', + ), + 3: Field( name='total_distance', type=BASE_TYPES[0x86], # uint32 - def_num=9, + def_num=3, scale=100, units='m', ), - 10: Field( - name='total_cycles', + 4: Field( + name='avg_speed', type=BASE_TYPES[0x86], # uint32 - def_num=10, - units='cycles', - subfields=( - SubField( - name='total_strokes', - def_num=10, - type=BASE_TYPES[0x86], # uint32 - units='strokes', - ref_fields=( - ReferenceField( - name='sport', - def_num=23, - value='cycling', - raw_value=2, - ), - ), - ), - ), - ), - 11: Field( - name='total_calories', - type=BASE_TYPES[0x84], # uint16 - def_num=11, - units='kcal', + def_num=4, + scale=1000, + units='m/s', ), - 12: Field( # If New Leaf - name='total_fat_calories', - type=BASE_TYPES[0x84], # uint16 - def_num=12, - units='kcal', + 9: Field( + name='start_time', + type=FIELD_TYPES['date_time'], + def_num=9, ), 13: Field( - name='avg_speed', + name='total_ascent', type=BASE_TYPES[0x84], # uint16 def_num=13, - scale=1000, - units='m/s', + units='m', ), 14: Field( - name='max_speed', + name='total_descent', type=BASE_TYPES[0x84], # uint16 def_num=14, - scale=1000, - units='m/s', - ), - 15: Field( - name='avg_heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=15, - units='bpm', - ), - 16: Field( - name='max_heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=16, - units='bpm', - ), - 17: Field( # total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time - name='avg_cadence', - type=BASE_TYPES[0x02], # uint8 - def_num=17, - units='rpm', - ), - 18: Field( - name='max_cadence', - type=BASE_TYPES[0x02], # uint8 - def_num=18, - units='rpm', - ), - 19: Field( # total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time - name='avg_power', - type=BASE_TYPES[0x84], # uint16 - def_num=19, - units='watts', - ), - 20: Field( - name='max_power', - type=BASE_TYPES[0x84], # uint16 - def_num=20, - units='watts', + units='m', ), 21: Field( - name='total_ascent', - type=BASE_TYPES[0x84], # uint16 + name='start_position_lat', + type=BASE_TYPES[0x85], # sint32 def_num=21, - units='m', + units='semicircles', ), 22: Field( - name='total_descent', - type=BASE_TYPES[0x84], # uint16 + name='start_position_long', + type=BASE_TYPES[0x85], # sint32 def_num=22, - units='m', + units='semicircles', ), 23: Field( - name='sport', - type=FIELD_TYPES['sport'], + name='end_position_lat', + type=BASE_TYPES[0x85], # sint32 def_num=23, + units='semicircles', ), 24: Field( - name='event_group', - type=BASE_TYPES[0x02], # uint8 + name='end_position_long', + type=BASE_TYPES[0x85], # sint32 def_num=24, + units='semicircles', ), - 25: Field( # North east corner latitude. - name='nec_lat', - type=BASE_TYPES[0x85], # sint32 + 25: Field( + name='max_speed', + type=BASE_TYPES[0x86], # uint32 def_num=25, - units='semicircles', + scale=1000, + units='m/s', ), - 26: Field( # North east corner longitude. - name='nec_long', + 26: Field( + name='avg_vert_speed', type=BASE_TYPES[0x85], # sint32 def_num=26, - units='semicircles', + scale=1000, + units='m/s', ), - 27: Field( # South west corner latitude. - name='swc_lat', - type=BASE_TYPES[0x85], # sint32 + 27: Field( + name='end_time', + type=FIELD_TYPES['date_time'], def_num=27, - units='semicircles', ), - 28: Field( # South west corner latitude. - name='swc_long', - type=BASE_TYPES[0x85], # sint32 + 28: Field( + name='total_calories', + type=BASE_TYPES[0x86], # uint32 def_num=28, - units='semicircles', - ), - 29: Field( - name='name', - type=BASE_TYPES[0x07], # string - def_num=29, - ), - 30: Field( - name='normalized_power', - type=BASE_TYPES[0x84], # uint16 - def_num=30, - units='watts', - ), - 31: Field( - name='left_right_balance', - type=FIELD_TYPES['left_right_balance_100'], - def_num=31, - ), - 32: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], - def_num=32, + units='kcal', ), - 33: Field( - name='total_work', + 74: Field( + name='start_elevation', type=BASE_TYPES[0x86], # uint32 - def_num=33, - units='J', - ), - 34: Field( - name='avg_altitude', - type=BASE_TYPES[0x84], # uint16 - def_num=34, + def_num=74, scale=5, offset=500, units='m', ), - 35: Field( - name='max_altitude', + 110: Field( + name='total_moving_time', + type=BASE_TYPES[0x86], # uint32 + def_num=110, + scale=1000, + units='s', + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 313: MessageType( + name='split_summary', + mesg_num=313, + fields={ + 0: Field( + name='split_type', + type=FIELD_TYPES['split_type'], + def_num=0, + ), + 3: Field( + name='num_splits', type=BASE_TYPES[0x84], # uint16 - def_num=35, - scale=5, - offset=500, - units='m', + def_num=3, ), - 36: Field( - name='gps_accuracy', - type=BASE_TYPES[0x02], # uint8 - def_num=36, - units='m', + 4: Field( + name='total_timer_time', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + scale=1000, + units='s', ), - 37: Field( - name='avg_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=37, + 5: Field( + name='total_distance', + type=BASE_TYPES[0x86], # uint32 + def_num=5, scale=100, - units='%', + units='m', ), - 38: Field( - name='avg_pos_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=38, - scale=100, - units='%', - ), - 39: Field( - name='avg_neg_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=39, - scale=100, - units='%', - ), - 40: Field( - name='max_pos_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=40, - scale=100, - units='%', - ), - 41: Field( - name='max_neg_grade', - type=BASE_TYPES[0x83], # sint16 - def_num=41, - scale=100, - units='%', - ), - 42: Field( - name='avg_temperature', - type=BASE_TYPES[0x01], # sint8 - def_num=42, - units='C', - ), - 43: Field( - name='max_temperature', - type=BASE_TYPES[0x01], # sint8 - def_num=43, - units='C', - ), - 44: Field( - name='total_moving_time', + 6: Field( + name='avg_speed', type=BASE_TYPES[0x86], # uint32 - def_num=44, - scale=1000, - units='s', - ), - 45: Field( - name='avg_pos_vertical_speed', - type=BASE_TYPES[0x83], # sint16 - def_num=45, - scale=1000, - units='m/s', - ), - 46: Field( - name='avg_neg_vertical_speed', - type=BASE_TYPES[0x83], # sint16 - def_num=46, - scale=1000, - units='m/s', - ), - 47: Field( - name='max_pos_vertical_speed', - type=BASE_TYPES[0x83], # sint16 - def_num=47, - scale=1000, - units='m/s', - ), - 48: Field( - name='max_neg_vertical_speed', - type=BASE_TYPES[0x83], # sint16 - def_num=48, + def_num=6, scale=1000, units='m/s', ), - 49: Field( - name='time_in_hr_zone', - type=BASE_TYPES[0x86], # uint32 - def_num=49, - scale=1000, - units='s', - ), - 50: Field( - name='time_in_speed_zone', - type=BASE_TYPES[0x86], # uint32 - def_num=50, - scale=1000, - units='s', - ), - 51: Field( - name='time_in_cadence_zone', - type=BASE_TYPES[0x86], # uint32 - def_num=51, - scale=1000, - units='s', - ), - 52: Field( - name='time_in_power_zone', + 7: Field( + name='max_speed', type=BASE_TYPES[0x86], # uint32 - def_num=52, + def_num=7, scale=1000, - units='s', + units='m/s', ), - 53: Field( - name='repetition_num', + 8: Field( + name='total_ascent', type=BASE_TYPES[0x84], # uint16 - def_num=53, + def_num=8, + units='m', ), - 54: Field( - name='min_altitude', + 9: Field( + name='total_descent', type=BASE_TYPES[0x84], # uint16 - def_num=54, - scale=5, - offset=500, + def_num=9, units='m', ), - 55: Field( - name='min_heart_rate', + 10: Field( + name='avg_heart_rate', type=BASE_TYPES[0x02], # uint8 - def_num=55, + def_num=10, units='bpm', ), - 56: Field( - name='active_time', + 11: Field( + name='max_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=11, + units='bpm', + ), + 12: Field( + name='avg_vert_speed', + type=BASE_TYPES[0x85], # sint32 + def_num=12, + scale=1000, + units='m/s', + ), + 13: Field( + name='total_calories', type=BASE_TYPES[0x86], # uint32 - def_num=56, + def_num=13, + units='kcal', + ), + 77: Field( + name='total_moving_time', + type=BASE_TYPES[0x86], # uint32 + def_num=77, scale=1000, units='s', ), - 57: Field( - name='wkt_step_index', + 254: Field( + name='message_index', type=FIELD_TYPES['message_index'], - def_num=57, - ), - 58: Field( - name='sport_event', - type=FIELD_TYPES['sport_event'], - def_num=58, + def_num=254, ), - 59: Field( - name='avg_left_torque_effectiveness', - type=BASE_TYPES[0x02], # uint8 - def_num=59, - scale=2, - units='percent', + }, + ), + 317: MessageType( + name='climb_pro', + mesg_num=317, + fields={ + 0: Field( + name='position_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=0, + units='semicircles', ), - 60: Field( - name='avg_right_torque_effectiveness', - type=BASE_TYPES[0x02], # uint8 - def_num=60, - scale=2, - units='percent', + 1: Field( + name='position_long', + type=BASE_TYPES[0x85], # sint32 + def_num=1, + units='semicircles', ), - 61: Field( - name='avg_left_pedal_smoothness', - type=BASE_TYPES[0x02], # uint8 - def_num=61, - scale=2, - units='percent', + 2: Field( + name='climb_pro_event', + type=FIELD_TYPES['climb_pro_event'], + def_num=2, ), - 62: Field( - name='avg_right_pedal_smoothness', - type=BASE_TYPES[0x02], # uint8 - def_num=62, - scale=2, - units='percent', + 3: Field( + name='climb_number', + type=BASE_TYPES[0x84], # uint16 + def_num=3, ), - 63: Field( - name='avg_combined_pedal_smoothness', + 4: Field( + name='climb_category', type=BASE_TYPES[0x02], # uint8 - def_num=63, - scale=2, - units='percent', + def_num=4, ), - 64: Field( - name='status', - type=FIELD_TYPES['segment_lap_status'], - def_num=64, + 5: Field( + name='current_dist', + type=BASE_TYPES[0x88], # float32 + def_num=5, + units='m', ), - 65: Field( - name='uuid', - type=BASE_TYPES[0x07], # string - def_num=65, + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 375: MessageType( + name='device_aux_battery_info', + mesg_num=375, + fields={ + 0: Field( + name='device_index', + type=FIELD_TYPES['device_index'], + def_num=0, ), - 66: Field( # fractional part of the avg_cadence - name='avg_fractional_cadence', - type=BASE_TYPES[0x02], # uint8 - def_num=66, - scale=128, - units='rpm', + 1: Field( + name='battery_voltage', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + scale=256, + units='V', ), - 67: Field( # fractional part of the max_cadence - name='max_fractional_cadence', - type=BASE_TYPES[0x02], # uint8 - def_num=67, - scale=128, - units='rpm', + 2: Field( + name='battery_status', + type=FIELD_TYPES['battery_status'], + def_num=2, ), - 68: Field( # fractional part of the total_cycles - name='total_fractional_cycles', + 3: Field( + name='battery_identifier', type=BASE_TYPES[0x02], # uint8 - def_num=68, - scale=128, - units='cycles', + def_num=3, ), - 69: Field( - name='front_gear_shift_count', + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + + + # ********************** Blood Pressure File Messages ********************** + 51: MessageType( + name='blood_pressure', + mesg_num=51, + fields={ + 0: Field( + name='systolic_pressure', type=BASE_TYPES[0x84], # uint16 - def_num=69, + def_num=0, + units='mmHg', ), - 70: Field( - name='rear_gear_shift_count', + 1: Field( + name='diastolic_pressure', type=BASE_TYPES[0x84], # uint16 - def_num=70, - ), - 71: Field( # Total time spent in the standing position - name='time_standing', - type=BASE_TYPES[0x86], # uint32 - def_num=71, - scale=1000, - units='s', + def_num=1, + units='mmHg', ), - 72: Field( # Number of transitions to the standing state - name='stand_count', + 2: Field( + name='mean_arterial_pressure', type=BASE_TYPES[0x84], # uint16 - def_num=72, - ), - 73: Field( # Average left platform center offset - name='avg_left_pco', - type=BASE_TYPES[0x01], # sint8 - def_num=73, - units='mm', - ), - 74: Field( # Average right platform center offset - name='avg_right_pco', - type=BASE_TYPES[0x01], # sint8 - def_num=74, - units='mm', - ), - 75: Field( # Average left power phase angles. Data value indexes defined by power_phase_type. - name='avg_left_power_phase', - type=BASE_TYPES[0x02], # uint8 - def_num=75, - scale=0.7111111, - units='degrees', - ), - 76: Field( # Average left power phase peak angles. Data value indexes defined by power_phase_type. - name='avg_left_power_phase_peak', - type=BASE_TYPES[0x02], # uint8 - def_num=76, - scale=0.7111111, - units='degrees', - ), - 77: Field( # Average right power phase angles. Data value indexes defined by power_phase_type. - name='avg_right_power_phase', - type=BASE_TYPES[0x02], # uint8 - def_num=77, - scale=0.7111111, - units='degrees', + def_num=2, + units='mmHg', ), - 78: Field( # Average right power phase peak angles. Data value indexes defined by power_phase_type. - name='avg_right_power_phase_peak', - type=BASE_TYPES[0x02], # uint8 - def_num=78, - scale=0.7111111, - units='degrees', + 3: Field( + name='map_3_sample_mean', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + units='mmHg', ), - 79: Field( # Average power by position. Data value indexes defined by rider_position_type. - name='avg_power_position', + 4: Field( + name='map_morning_values', type=BASE_TYPES[0x84], # uint16 - def_num=79, - units='watts', + def_num=4, + units='mmHg', ), - 80: Field( # Maximum power by position. Data value indexes defined by rider_position_type. - name='max_power_position', + 5: Field( + name='map_evening_values', type=BASE_TYPES[0x84], # uint16 - def_num=80, - units='watts', + def_num=5, + units='mmHg', ), - 81: Field( # Average cadence by position. Data value indexes defined by rider_position_type. - name='avg_cadence_position', + 6: Field( + name='heart_rate', type=BASE_TYPES[0x02], # uint8 - def_num=81, - units='rpm', + def_num=6, + units='bpm', ), - 82: Field( # Maximum cadence by position. Data value indexes defined by rider_position_type. - name='max_cadence_position', - type=BASE_TYPES[0x02], # uint8 - def_num=82, - units='rpm', + 7: Field( + name='heart_rate_type', + type=FIELD_TYPES['hr_type'], + def_num=7, ), - 83: Field( # Manufacturer that produced the segment - name='manufacturer', - type=FIELD_TYPES['manufacturer'], - def_num=83, + 8: Field( + name='status', + type=FIELD_TYPES['bp_status'], + def_num=8, ), - 253: FIELD_TYPE_TIMESTAMP, # Lap end time. - 254: Field( - name='message_index', + 9: Field( # Associates this blood pressure message to a user. This corresponds to the index of the user profile message in the blood pressure file. + name='user_profile_index', type=FIELD_TYPES['message_index'], - def_num=254, + def_num=9, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 149: MessageType( # Unique Identification data for an individual segment leader within a segment file - name='segment_leaderboard_entry', - mesg_num=149, + + + # ************************** Course File Messages ************************** + 31: MessageType( + name='course', + mesg_num=31, fields={ - 0: Field( # Friendly name assigned to leader - name='name', - type=BASE_TYPES[0x07], # string - def_num=0, - ), - 1: Field( # Leader classification - name='type', - type=FIELD_TYPES['segment_leaderboard_type'], - def_num=1, - ), - 2: Field( # Primary user ID of this leader - name='group_primary_key', - type=BASE_TYPES[0x86], # uint32 - def_num=2, - ), - 3: Field( # ID of the activity associated with this leader time - name='activity_id', - type=BASE_TYPES[0x86], # uint32 - def_num=3, - ), - 4: Field( # Segment Time (includes pauses) - name='segment_time', - type=BASE_TYPES[0x86], # uint32 + 4: Field( + name='sport', + type=FIELD_TYPES['sport'], def_num=4, - scale=1000, - units='s', ), - 5: Field( # String version of the activity_id. 21 characters long, express in decimal - name='activity_id_string', + 5: Field( + name='name', type=BASE_TYPES[0x07], # string def_num=5, ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 6: Field( + name='capabilities', + type=FIELD_TYPES['course_capabilities'], + def_num=6, + ), + 7: Field( + name='sub_sport', + type=FIELD_TYPES['sub_sport'], + def_num=7, ), }, ), - 150: MessageType( # Navigation and race evaluation point for a segment decribing a point along the segment path and time it took each segment leader to reach that point - name='segment_point', - mesg_num=150, + 32: MessageType( + name='course_point', + mesg_num=32, fields={ 1: Field( + name='timestamp', + type=FIELD_TYPES['date_time'], + def_num=1, + ), + 2: Field( name='position_lat', type=BASE_TYPES[0x85], # sint32 - def_num=1, + def_num=2, units='semicircles', ), - 2: Field( + 3: Field( name='position_long', type=BASE_TYPES[0x85], # sint32 - def_num=2, + def_num=3, units='semicircles', ), - 3: Field( # Accumulated distance along the segment at the described point + 4: Field( name='distance', type=BASE_TYPES[0x86], # uint32 - def_num=3, - scale=100, - units='m', - ), - 4: Field( # Accumulated altitude along the segment at the described point - name='altitude', - type=BASE_TYPES[0x84], # uint16 def_num=4, - scale=5, - offset=500, + scale=100, units='m', ), - 5: Field( # Accumualted time each leader board member required to reach the described point. This value is zero for all leader board members at the starting point of the segment. - name='leader_time', - type=BASE_TYPES[0x86], # uint32 + 5: Field( + name='type', + type=FIELD_TYPES['course_point'], def_num=5, - scale=1000, - units='s', + ), + 6: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=6, + ), + 8: Field( + name='favorite', + type=FIELD_TYPES['bool'], + def_num=8, ), 254: Field( name='message_index', @@ -9631,40 +10876,48 @@ ), }, ), - 158: MessageType( - name='workout_session', - mesg_num=158, + + + # ************************** Device File Messages ************************** + 1: MessageType( + name='capabilities', + mesg_num=1, fields={ - 0: Field( - name='sport', - type=FIELD_TYPES['sport'], + 0: Field( # Use language_bits_x types where x is index of array. + name='languages', + type=BASE_TYPES[0x0A], # uint8z def_num=0, ), - 1: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], + 1: Field( # Use sport_bits_x types where x is index of array. + name='sports', + type=FIELD_TYPES['sport_bits_0'], def_num=1, ), - 2: Field( - name='num_valid_steps', - type=BASE_TYPES[0x84], # uint16 - def_num=2, + 21: Field( + name='workouts_supported', + type=FIELD_TYPES['workout_capabilities'], + def_num=21, + ), + 23: Field( + name='connectivity_supported', + type=FIELD_TYPES['connectivity_capabilities'], + def_num=23, ), + }, + ), + 35: MessageType( + name='software', + mesg_num=35, + fields={ 3: Field( - name='first_step_index', + name='version', type=BASE_TYPES[0x84], # uint16 def_num=3, - ), - 4: Field( - name='pool_length', - type=BASE_TYPES[0x84], # uint16 - def_num=4, scale=100, - units='m', ), 5: Field( - name='pool_length_unit', - type=FIELD_TYPES['display_measure'], + name='part_number', + type=BASE_TYPES[0x07], # string def_num=5, ), 254: Field( @@ -9674,42 +10927,102 @@ ), }, ), - 159: MessageType( - name='watchface_settings', - mesg_num=159, + 37: MessageType( + name='file_capabilities', + mesg_num=37, fields={ 0: Field( - name='mode', - type=FIELD_TYPES['watchface_mode'], + name='type', + type=FIELD_TYPES['file'], def_num=0, ), 1: Field( - name='layout', - type=BASE_TYPES[0x0D], # byte + name='flags', + type=FIELD_TYPES['file_flags'], + def_num=1, + ), + 2: Field( + name='directory', + type=BASE_TYPES[0x07], # string + def_num=2, + ), + 3: Field( + name='max_count', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + ), + 4: Field( + name='max_size', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + units='bytes', + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 38: MessageType( + name='mesg_capabilities', + mesg_num=38, + fields={ + 0: Field( + name='file', + type=FIELD_TYPES['file'], + def_num=0, + ), + 1: Field( + name='mesg_num', + type=FIELD_TYPES['mesg_num'], def_num=1, + ), + 2: Field( + name='count_type', + type=FIELD_TYPES['mesg_count'], + def_num=2, + ), + 3: Field( + name='count', + type=BASE_TYPES[0x84], # uint16 + def_num=3, subfields=( SubField( - name='analog_layout', - def_num=1, - type=FIELD_TYPES['analog_watchface_layout'], + name='max_per_file', + def_num=3, + type=BASE_TYPES[0x84], # uint16 ref_fields=( ReferenceField( - name='mode', - def_num=0, - value='analog', + name='count_type', + def_num=2, + value='max_per_file', raw_value=1, ), ), ), SubField( - name='digital_layout', - def_num=1, - type=FIELD_TYPES['digital_watchface_layout'], + name='max_per_file_type', + def_num=3, + type=BASE_TYPES[0x84], # uint16 ref_fields=( ReferenceField( - name='mode', - def_num=0, - value='digital', + name='count_type', + def_num=2, + value='max_per_file_type', + raw_value=2, + ), + ), + ), + SubField( + name='num_per_file', + def_num=3, + type=BASE_TYPES[0x84], # uint16 + ref_fields=( + ReferenceField( + name='count_type', + def_num=2, + value='num_per_file', raw_value=0, ), ), @@ -9723,1732 +11036,2283 @@ ), }, ), - 160: MessageType( - name='gps_metadata', - mesg_num=160, + 39: MessageType( + name='field_capabilities', + mesg_num=39, fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( + name='file', + type=FIELD_TYPES['file'], def_num=0, - units='ms', ), 1: Field( - name='position_lat', - type=BASE_TYPES[0x85], # sint32 + name='mesg_num', + type=FIELD_TYPES['mesg_num'], def_num=1, - units='semicircles', ), 2: Field( - name='position_long', - type=BASE_TYPES[0x85], # sint32 + name='field_num', + type=BASE_TYPES[0x02], # uint8 def_num=2, - units='semicircles', ), 3: Field( - name='enhanced_altitude', - type=BASE_TYPES[0x86], # uint32 + name='count', + type=BASE_TYPES[0x84], # uint16 def_num=3, - scale=5, - offset=500, - units='m', - ), - 4: Field( - name='enhanced_speed', - type=BASE_TYPES[0x86], # uint32 - def_num=4, - scale=1000, - units='m/s', ), - 5: Field( - name='heading', - type=BASE_TYPES[0x84], # uint16 - def_num=5, - scale=100, - units='degrees', + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, ), - 6: Field( # Used to correlate UTC to system time if the timestamp of the message is in system time. This UTC time is derived from the GPS data. - name='utc_timestamp', - type=FIELD_TYPES['date_time'], - def_num=6, - units='s', + }, + ), + 106: MessageType( + name='slave_device', + mesg_num=106, + fields={ + 0: Field( + name='manufacturer', + type=FIELD_TYPES['manufacturer'], + def_num=0, ), - 7: Field( # velocity[0] is lon velocity. Velocity[1] is lat velocity. Velocity[2] is altitude velocity. - name='velocity', - type=BASE_TYPES[0x83], # sint16 - def_num=7, - scale=100, - units='m/s', + 1: Field( + name='product', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + subfields=( + SubField( + name='favero_product', + def_num=1, + type=FIELD_TYPES['favero_product'], + ref_fields=( + ReferenceField( + name='manufacturer', + def_num=0, + value='favero_electronics', + raw_value=263, + ), + ), + ), + SubField( + name='garmin_product', + def_num=1, + type=FIELD_TYPES['garmin_product'], + ref_fields=( + ReferenceField( + name='manufacturer', + def_num=0, + value='garmin', + raw_value=1, + ), + ReferenceField( + name='manufacturer', + def_num=0, + value='dynastream', + raw_value=15, + ), + ReferenceField( + name='manufacturer', + def_num=0, + value='dynastream_oem', + raw_value=13, + ), + ReferenceField( + name='manufacturer', + def_num=0, + value='tacx', + raw_value=89, + ), + ), + ), + ), ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp. }, ), - 161: MessageType( - name='camera_event', - mesg_num=161, + + + # ************************** Goals File Messages *************************** + 15: MessageType( + name='goal', + mesg_num=15, fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( + name='sport', + type=FIELD_TYPES['sport'], def_num=0, - units='ms', ), 1: Field( - name='camera_event_type', - type=FIELD_TYPES['camera_event_type'], + name='sub_sport', + type=FIELD_TYPES['sub_sport'], def_num=1, ), 2: Field( - name='camera_file_uuid', - type=BASE_TYPES[0x07], # string + name='start_date', + type=FIELD_TYPES['date_time'], def_num=2, ), 3: Field( - name='camera_orientation', - type=FIELD_TYPES['camera_orientation_type'], - def_num=3, - ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp. - }, - ), - 162: MessageType( - name='timestamp_correlation', - mesg_num=162, - fields={ - 0: Field( # Fractional part of the UTC timestamp at the time the system timestamp was recorded. - name='fractional_timestamp', - type=BASE_TYPES[0x84], # uint16 - def_num=0, - scale=32768, - units='s', - ), - 1: Field( # Whole second part of the system timestamp - name='system_timestamp', + name='end_date', type=FIELD_TYPES['date_time'], - def_num=1, - units='s', - ), - 2: Field( # Fractional part of the system timestamp - name='fractional_system_timestamp', - type=BASE_TYPES[0x84], # uint16 - def_num=2, - scale=32768, - units='s', - ), - 3: Field( # timestamp epoch expressed in local time used to convert timestamps to local time - name='local_timestamp', - type=FIELD_TYPES['local_date_time'], def_num=3, - units='s', ), - 4: Field( # Millisecond part of the UTC timestamp at the time the system timestamp was recorded. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 4: Field( + name='type', + type=FIELD_TYPES['goal'], def_num=4, - units='ms', ), - 5: Field( # Millisecond part of the system timestamp - name='system_timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 5: Field( + name='value', + type=BASE_TYPES[0x86], # uint32 def_num=5, - units='ms', - ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of UTC timestamp at the time the system timestamp was recorded. - }, - ), - 164: MessageType( - name='gyroscope_data', - mesg_num=164, - fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 - def_num=0, - units='ms', ), - 1: Field( # Each time in the array describes the time at which the gyro sample with the corrosponding index was taken. Limited to 30 samples in each message. The samples may span across seconds. Array size must match the number of samples in gyro_x and gyro_y and gyro_z - name='sample_time_offset', - type=BASE_TYPES[0x84], # uint16 - def_num=1, - units='ms', + 6: Field( + name='repeat', + type=FIELD_TYPES['bool'], + def_num=6, ), - 2: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='gyro_x', - type=BASE_TYPES[0x84], # uint16 - def_num=2, - units='counts', + 7: Field( + name='target_value', + type=BASE_TYPES[0x86], # uint32 + def_num=7, ), - 3: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='gyro_y', - type=BASE_TYPES[0x84], # uint16 - def_num=3, - units='counts', + 8: Field( + name='recurrence', + type=FIELD_TYPES['goal_recurrence'], + def_num=8, ), - 4: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='gyro_z', + 9: Field( + name='recurrence_value', type=BASE_TYPES[0x84], # uint16 - def_num=4, - units='counts', + def_num=9, ), - 5: Field( # Calibrated gyro reading - name='calibrated_gyro_x', - type=BASE_TYPES[0x88], # float32 - def_num=5, - units='deg/s', + 10: Field( + name='enabled', + type=FIELD_TYPES['bool'], + def_num=10, ), - 6: Field( # Calibrated gyro reading - name='calibrated_gyro_y', - type=BASE_TYPES[0x88], # float32 - def_num=6, - units='deg/s', + 11: Field( + name='source', + type=FIELD_TYPES['goal_source'], + def_num=11, ), - 7: Field( # Calibrated gyro reading - name='calibrated_gyro_z', - type=BASE_TYPES[0x88], # float32 - def_num=7, - units='deg/s', + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 165: MessageType( - name='accelerometer_data', - mesg_num=165, + + + # ************************ Monitoring File Messages ************************ + 55: MessageType( + name='monitoring', + mesg_num=55, fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( # Associates this data to device_info message. Not required for file with single device (sensor). + name='device_index', + type=FIELD_TYPES['device_index'], def_num=0, - units='ms', ), - 1: Field( # Each time in the array describes the time at which the accelerometer sample with the corrosponding index was taken. Limited to 30 samples in each message. The samples may span across seconds. Array size must match the number of samples in accel_x and accel_y and accel_z - name='sample_time_offset', + 1: Field( # Accumulated total calories. Maintained by MonitoringReader for each activity_type. See SDK documentation + name='calories', type=BASE_TYPES[0x84], # uint16 def_num=1, - units='ms', + units='kcal', ), - 2: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='accel_x', - type=BASE_TYPES[0x84], # uint16 + 2: Field( # Accumulated distance. Maintained by MonitoringReader for each activity_type. See SDK documentation. + name='distance', + type=BASE_TYPES[0x86], # uint32 def_num=2, - units='counts', + scale=100, + units='m', ), - 3: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='accel_y', - type=BASE_TYPES[0x84], # uint16 + 3: Field( # Accumulated cycles. Maintained by MonitoringReader for each activity_type. See SDK documentation. + name='cycles', + type=BASE_TYPES[0x86], # uint32 def_num=3, - units='counts', + scale=2, + units='cycles', + subfields=( + SubField( + name='steps', + def_num=3, + type=BASE_TYPES[0x86], # uint32 + units='steps', + ref_fields=( + ReferenceField( + name='activity_type', + def_num=5, + value='walking', + raw_value=6, + ), + ReferenceField( + name='activity_type', + def_num=5, + value='running', + raw_value=1, + ), + ), + ), + SubField( + name='strokes', + def_num=3, + type=BASE_TYPES[0x86], # uint32 + scale=2, + units='strokes', + ref_fields=( + ReferenceField( + name='activity_type', + def_num=5, + value='cycling', + raw_value=2, + ), + ReferenceField( + name='activity_type', + def_num=5, + value='swimming', + raw_value=5, + ), + ), + ), + ), ), - 4: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='accel_z', - type=BASE_TYPES[0x84], # uint16 + 4: Field( + name='active_time', + type=BASE_TYPES[0x86], # uint32 def_num=4, - units='counts', + scale=1000, + units='s', ), - 5: Field( # Calibrated accel reading - name='calibrated_accel_x', - type=BASE_TYPES[0x88], # float32 + 5: Field( + name='activity_type', + type=FIELD_TYPES['activity_type'], def_num=5, - units='g', ), - 6: Field( # Calibrated accel reading - name='calibrated_accel_y', - type=BASE_TYPES[0x88], # float32 + 6: Field( + name='activity_subtype', + type=FIELD_TYPES['activity_subtype'], def_num=6, - units='g', ), - 7: Field( # Calibrated accel reading - name='calibrated_accel_z', - type=BASE_TYPES[0x88], # float32 + 7: Field( + name='activity_level', + type=FIELD_TYPES['activity_level'], def_num=7, - units='g', ), - 8: Field( # Calibrated accel reading - name='compressed_calibrated_accel_x', - type=BASE_TYPES[0x83], # sint16 + 8: Field( + name='distance_16', + type=BASE_TYPES[0x84], # uint16 def_num=8, - units='mG', + units='100*m', ), - 9: Field( # Calibrated accel reading - name='compressed_calibrated_accel_y', - type=BASE_TYPES[0x83], # sint16 + 9: Field( + name='cycles_16', + type=BASE_TYPES[0x84], # uint16 def_num=9, - units='mG', + units='2*cycles or steps', ), - 10: Field( # Calibrated accel reading - name='compressed_calibrated_accel_z', - type=BASE_TYPES[0x83], # sint16 + 10: Field( + name='active_time_16', + type=BASE_TYPES[0x84], # uint16 def_num=10, - units='mG', + units='s', ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp - }, - ), - 167: MessageType( - name='three_d_sensor_calibration', - mesg_num=167, - fields={ - 0: Field( # Indicates which sensor the calibration is for - name='sensor_type', - type=FIELD_TYPES['sensor_type'], - def_num=0, + 11: Field( # Must align to logging interval, for example, time must be 00:00:00 for daily log. + name='local_timestamp', + type=FIELD_TYPES['local_date_time'], + def_num=11, ), - 1: Field( # Calibration factor used to convert from raw ADC value to degrees, g, etc. - name='calibration_factor', - type=BASE_TYPES[0x86], # uint32 - def_num=1, - subfields=( - SubField( # Accelerometer calibration factor - name='accel_cal_factor', - def_num=1, - type=BASE_TYPES[0x86], # uint32 - units='g', - ref_fields=( - ReferenceField( - name='sensor_type', - def_num=0, - value='accelerometer', - raw_value=0, - ), - ), + 12: Field( # Avg temperature during the logging interval ended at timestamp + name='temperature', + type=BASE_TYPES[0x83], # sint16 + def_num=12, + scale=100, + units='C', + ), + 14: Field( # Min temperature during the logging interval ended at timestamp + name='temperature_min', + type=BASE_TYPES[0x83], # sint16 + def_num=14, + scale=100, + units='C', + ), + 15: Field( # Max temperature during the logging interval ended at timestamp + name='temperature_max', + type=BASE_TYPES[0x83], # sint16 + def_num=15, + scale=100, + units='C', + ), + 16: Field( # Indexed using minute_activity_level enum + name='activity_time', + type=BASE_TYPES[0x84], # uint16 + def_num=16, + units='minutes', + ), + 19: Field( + name='active_calories', + type=BASE_TYPES[0x84], # uint16 + def_num=19, + units='kcal', + ), + 24: Field( # Indicates single type / intensity for duration since last monitoring message. + name='current_activity_type_intensity', + type=BASE_TYPES[0x0D], # byte + def_num=24, + components=( + ComponentField( + name='activity_type', + def_num=5, + accumulate=False, + bits=5, + bit_offset=0, ), - SubField( # Gyro calibration factor - name='gyro_cal_factor', - def_num=1, - type=BASE_TYPES[0x86], # uint32 - units='deg/s', - ref_fields=( - ReferenceField( - name='sensor_type', - def_num=0, - value='gyroscope', - raw_value=1, - ), - ), + ComponentField( + name='intensity', + def_num=28, + accumulate=False, + bits=3, + bit_offset=5, ), ), ), - 2: Field( # Calibration factor divisor - name='calibration_divisor', - type=BASE_TYPES[0x86], # uint32 - def_num=2, - units='counts', + 25: Field( + name='timestamp_min_8', + type=BASE_TYPES[0x02], # uint8 + def_num=25, + units='min', ), - 3: Field( # Level shift value used to shift the ADC value back into range - name='level_shift', - type=BASE_TYPES[0x86], # uint32 - def_num=3, + 26: Field( + name='timestamp_16', + type=BASE_TYPES[0x84], # uint16 + def_num=26, + units='s', ), - 4: Field( # Internal calibration factors, one for each: xy, yx, zx - name='offset_cal', - type=BASE_TYPES[0x85], # sint32 - def_num=4, + 27: Field( + name='heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=27, + units='bpm', ), - 5: Field( # 3 x 3 rotation matrix (row major) - name='orientation_matrix', - type=BASE_TYPES[0x85], # sint32 - def_num=5, - scale=65535, + 28: Field( + name='intensity', + type=BASE_TYPES[0x02], # uint8 + def_num=28, + scale=10, ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp - }, - ), - 169: MessageType( - name='video_frame', - mesg_num=169, - fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', + 29: Field( + name='duration_min', type=BASE_TYPES[0x84], # uint16 - def_num=0, - units='ms', + def_num=29, + units='min', ), - 1: Field( # Number of the frame that the timestamp and timestamp_ms correlate to - name='frame_number', + 30: Field( + name='duration', type=BASE_TYPES[0x86], # uint32 - def_num=1, + def_num=30, + units='s', ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp + 31: Field( + name='ascent', + type=BASE_TYPES[0x86], # uint32 + def_num=31, + scale=1000, + units='m', + ), + 32: Field( + name='descent', + type=BASE_TYPES[0x86], # uint32 + def_num=32, + scale=1000, + units='m', + ), + 33: Field( + name='moderate_activity_minutes', + type=BASE_TYPES[0x84], # uint16 + def_num=33, + units='minutes', + ), + 34: Field( + name='vigorous_activity_minutes', + type=BASE_TYPES[0x84], # uint16 + def_num=34, + units='minutes', + ), + 253: FIELD_TYPE_TIMESTAMP, # Must align to logging interval, for example, time must be 00:00:00 for daily log. }, ), - 174: MessageType( - name='obdii_data', - mesg_num=174, + 103: MessageType( + name='monitoring_info', + mesg_num=103, fields={ - 0: Field( # Fractional part of timestamp, added to timestamp - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( # Use to convert activity timestamps to local time if device does not support time zone and daylight savings time correction. + name='local_timestamp', + type=FIELD_TYPES['local_date_time'], def_num=0, - units='ms', + units='s', ), - 1: Field( # Offset of PID reading [i] from start_timestamp+start_timestamp_ms. Readings may span accross seconds. - name='time_offset', - type=BASE_TYPES[0x84], # uint16 + 1: Field( + name='activity_type', + type=FIELD_TYPES['activity_type'], def_num=1, - units='ms', - ), - 2: Field( # Parameter ID - name='pid', - type=BASE_TYPES[0x0D], # byte - def_num=2, ), - 3: Field( # Raw parameter data - name='raw_data', - type=BASE_TYPES[0x0D], # byte + 3: Field( # Indexed by activity_type + name='cycles_to_distance', + type=BASE_TYPES[0x84], # uint16 def_num=3, + scale=5000, + units='m/cycle', ), - 4: Field( # Optional, data size of PID[i]. If not specified refer to SAE J1979. - name='pid_data_size', - type=BASE_TYPES[0x02], # uint8 + 4: Field( # Indexed by activity_type + name='cycles_to_calories', + type=BASE_TYPES[0x84], # uint16 def_num=4, + scale=5000, + units='kcal/cycle', ), - 5: Field( # System time associated with sample expressed in ms, can be used instead of time_offset. There will be a system_time value for each raw_data element. For multibyte pids the system_time is repeated. - name='system_time', - type=BASE_TYPES[0x86], # uint32 - def_num=5, - ), - 6: Field( # Timestamp of first sample recorded in the message. Used with time_offset to generate time of each sample - name='start_timestamp', - type=FIELD_TYPES['date_time'], - def_num=6, - ), - 7: Field( # Fractional part of start_timestamp - name='start_timestamp_ms', + 5: Field( + name='resting_metabolic_rate', type=BASE_TYPES[0x84], # uint16 - def_num=7, - units='ms', + def_num=5, + units='kcal/day', ), - 253: FIELD_TYPE_TIMESTAMP, # Timestamp message was output + 253: FIELD_TYPE_TIMESTAMP, }, ), - 177: MessageType( - name='nmea_sentence', - mesg_num=177, + 132: MessageType( + name='hr', + mesg_num=132, fields={ - 0: Field( # Fractional part of timestamp, added to timestamp - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( + name='fractional_timestamp', + type=BASE_TYPES[0x84], # uint16 def_num=0, - units='ms', + scale=32768, + units='s', ), - 1: Field( # NMEA sentence - name='sentence', - type=BASE_TYPES[0x07], # string + 1: Field( + name='time256', + type=BASE_TYPES[0x02], # uint8 def_num=1, + scale=256, + units='s', + components=( + ComponentField( + name='fractional_timestamp', + def_num=0, + scale=256, + units='s', + accumulate=False, + bits=8, + bit_offset=0, + ), + ), ), - 253: FIELD_TYPE_TIMESTAMP, # Timestamp message was output + 6: Field( + name='filtered_bpm', + type=BASE_TYPES[0x02], # uint8 + def_num=6, + units='bpm', + ), + 9: Field( + name='event_timestamp', + type=BASE_TYPES[0x86], # uint32 + def_num=9, + scale=1024, + units='s', + ), + 10: Field( + name='event_timestamp_12', + type=BASE_TYPES[0x0D], # byte + def_num=10, + components=( + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=0, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=12, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=24, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=36, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=48, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=60, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=72, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=84, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=96, + ), + ComponentField( + name='event_timestamp', + def_num=9, + scale=1024, + units='s', + accumulate=True, + bits=12, + bit_offset=108, + ), + ), + ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 178: MessageType( - name='aviation_attitude', - mesg_num=178, + 211: MessageType( + name='monitoring_hr_data', + mesg_num=211, fields={ - 0: Field( # Fractional part of timestamp, added to timestamp - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( # 7-day rolling average + name='resting_heart_rate', + type=BASE_TYPES[0x02], # uint8 def_num=0, - units='ms', + units='bpm', ), - 1: Field( # System time associated with sample expressed in ms. - name='system_time', - type=BASE_TYPES[0x86], # uint32 + 1: Field( # RHR for today only. (Feeds into 7-day average) + name='current_day_resting_heart_rate', + type=BASE_TYPES[0x02], # uint8 def_num=1, - units='ms', + units='bpm', ), - 2: Field( # Range -PI/2 to +PI/2 - name='pitch', + 253: FIELD_TYPE_TIMESTAMP, # Must align to logging interval, for example, time must be 00:00:00 for daily log. + }, + ), + 227: MessageType( # Value from 1 to 100 calculated by FirstBeat + name='stress_level', + mesg_num=227, + fields={ + 0: Field( + name='stress_level_value', type=BASE_TYPES[0x83], # sint16 - def_num=2, - scale=10430.38, - units='radians', + def_num=0, ), - 3: Field( # Range -PI to +PI - name='roll', - type=BASE_TYPES[0x83], # sint16 - def_num=3, - scale=10430.38, - units='radians', + 1: Field( # Time stress score was calculated + name='stress_level_time', + type=FIELD_TYPES['date_time'], + def_num=1, + units='s', ), - 4: Field( # Range -78.4 to +78.4 (-8 Gs to 8 Gs) - name='accel_lateral', - type=BASE_TYPES[0x83], # sint16 - def_num=4, - scale=100, - units='m/s^2', + }, + ), + 229: MessageType( + name='max_met_data', + mesg_num=229, + fields={ + 0: Field( # Time maxMET and vo2 were calculated + name='update_time', + type=FIELD_TYPES['date_time'], + def_num=0, ), - 5: Field( # Range -78.4 to +78.4 (-8 Gs to 8 Gs) - name='accel_normal', - type=BASE_TYPES[0x83], # sint16 + 2: Field( + name='vo2_max', + type=BASE_TYPES[0x84], # uint16 + def_num=2, + scale=10, + units='mL/kg/min', + ), + 5: Field( + name='sport', + type=FIELD_TYPES['sport'], def_num=5, - scale=100, - units='m/s^2', ), - 6: Field( # Range -8.727 to +8.727 (-500 degs/sec to +500 degs/sec) - name='turn_rate', - type=BASE_TYPES[0x83], # sint16 + 6: Field( + name='sub_sport', + type=FIELD_TYPES['sub_sport'], def_num=6, - scale=1024, - units='radians/second', - ), - 7: Field( - name='stage', - type=FIELD_TYPES['attitude_stage'], - def_num=7, ), - 8: Field( # The percent complete of the current attitude stage. Set to 0 for attitude stages 0, 1 and 2 and to 100 for attitude stage 3 by AHRS modules that do not support it. Range - 100 - name='attitude_stage_complete', - type=BASE_TYPES[0x02], # uint8 + 8: Field( + name='max_met_category', + type=FIELD_TYPES['max_met_category'], def_num=8, - units='%', ), - 9: Field( # Track Angle/Heading Range 0 - 2pi - name='track', - type=BASE_TYPES[0x84], # uint16 + 9: Field( # Indicates if calibrated data was used in the calculation + name='calibrated_data', + type=FIELD_TYPES['bool'], def_num=9, - scale=10430.38, - units='radians', ), - 10: Field( - name='validity', - type=FIELD_TYPES['attitude_validity'], - def_num=10, + 12: Field( # Indicates if the estimate was obtained using a chest strap or wrist heart rate + name='hr_source', + type=FIELD_TYPES['max_met_heart_rate_source'], + def_num=12, + ), + 13: Field( # Indidcates if the estimate was obtained using onboard GPS or connected GPS + name='speed_source', + type=FIELD_TYPES['max_met_speed_source'], + def_num=13, ), - 253: FIELD_TYPE_TIMESTAMP, # Timestamp message was output }, ), - 184: MessageType( - name='video', - mesg_num=184, + 269: MessageType( + name='spo2_data', + mesg_num=269, fields={ 0: Field( - name='url', - type=BASE_TYPES[0x07], # string + name='reading_spo2', + type=BASE_TYPES[0x02], # uint8 def_num=0, + units='percent', ), 1: Field( - name='hosting_provider', - type=BASE_TYPES[0x07], # string + name='reading_confidence', + type=BASE_TYPES[0x02], # uint8 def_num=1, ), - 2: Field( # Playback time of video - name='duration', - type=BASE_TYPES[0x86], # uint32 + 2: Field( # Mode when data was captured + name='mode', + type=FIELD_TYPES['spo2_measurement_type'], def_num=2, - units='ms', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 185: MessageType( - name='video_title', - mesg_num=185, + 302: MessageType( # Raw accelerometer data used for HSA custom data logging + name='hsa_accelerometer_data', + mesg_num=302, fields={ - 0: Field( # Total number of title parts - name='message_count', + 0: Field( # Millisecond resolution of the timestamp + name='timestamp_ms', type=BASE_TYPES[0x84], # uint16 def_num=0, + units='ms', ), - 1: Field( - name='text', - type=BASE_TYPES[0x07], # string + 1: Field( # Sampling Interval in Milliseconds + name='sampling_interval', + type=BASE_TYPES[0x84], # uint16 def_num=1, + units='ms', ), - 254: Field( # Long titles will be split into multiple parts - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 2: Field( # X-Axis Measurement + name='accel_x', + type=BASE_TYPES[0x83], # sint16 + def_num=2, + scale=1.024, + units='mG', + ), + 3: Field( # Y-Axis Measurement + name='accel_y', + type=BASE_TYPES[0x83], # sint16 + def_num=3, + scale=1.024, + units='mG', + ), + 4: Field( # Z-Axis Measurement + name='accel_z', + type=BASE_TYPES[0x83], # sint16 + def_num=4, + scale=1.024, + units='mG', + ), + 5: Field( # 32 kHz timestamp + name='timestamp_32k', + type=BASE_TYPES[0x86], # uint32 + def_num=5, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 186: MessageType( - name='video_description', - mesg_num=186, + 304: MessageType( # User's current daily step data used for HSA custom data logging + name='hsa_step_data', + mesg_num=304, fields={ - 0: Field( # Total number of description parts - name='message_count', + 0: Field( # Processing interval length in seconds. File start: 0xFFFFFFEF File stop: 0xFFFFFFEE + name='processing_interval', type=BASE_TYPES[0x84], # uint16 def_num=0, + units='s', ), - 1: Field( - name='text', - type=BASE_TYPES[0x07], # string + 1: Field( # Total step sum + name='steps', + type=BASE_TYPES[0x86], # uint32 def_num=1, + units='steps', ), - 254: Field( # Long descriptions will be split into multiple parts - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, - ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 187: MessageType( - name='video_clip', - mesg_num=187, + 305: MessageType( # User's current SpO2 data used for HSA custom data logging + name='hsa_spo2_data', + mesg_num=305, fields={ - 0: Field( - name='clip_number', + 0: Field( # Processing interval length in seconds + name='processing_interval', type=BASE_TYPES[0x84], # uint16 def_num=0, + units='s', ), - 1: Field( - name='start_timestamp', - type=FIELD_TYPES['date_time'], + 1: Field( # SpO2 Reading: [70,100] Blank: 240 + name='reading_spo2', + type=BASE_TYPES[0x02], # uint8 def_num=1, + units='percent', ), - 2: Field( - name='start_timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 2: Field( # SpO2 Confidence: [0,254] + name='confidence', + type=BASE_TYPES[0x02], # uint8 def_num=2, ), - 3: Field( - name='end_timestamp', - type=FIELD_TYPES['date_time'], - def_num=3, - ), - 4: Field( - name='end_timestamp_ms', + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 306: MessageType( # User's current stress data used for HSA custom data logging + name='hsa_stress_data', + mesg_num=306, + fields={ + 0: Field( # Processing interval length in seconds + name='processing_interval', type=BASE_TYPES[0x84], # uint16 - def_num=4, - ), - 6: Field( # Start of clip in video time - name='clip_start', - type=BASE_TYPES[0x86], # uint32 - def_num=6, - units='ms', + def_num=0, + units='s', ), - 7: Field( # End of clip in video time - name='clip_end', - type=BASE_TYPES[0x86], # uint32 - def_num=7, - units='ms', + 1: Field( # Stress Level: [0,100] Off wrist: -1 Excess motion: -2 Not enough data: -3 Recovering from exercise: -4 Unidentified: -5 Blank: -16 + name='stress_level', + type=BASE_TYPES[0x01], # sint8 + def_num=1, + units='s', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 188: MessageType( - name='ohr_settings', - mesg_num=188, + 307: MessageType( # User's current respiration data used for HSA custom data logging + name='hsa_respiration_data', + mesg_num=307, fields={ - 0: Field( - name='enabled', - type=FIELD_TYPES['switch'], + 0: Field( # Processing interval length in seconds + name='processing_interval', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='s', + ), + 1: Field( # Breaths / min: [1,100] Invalid: 255 Excess motion: 254 Off wrist: 253 Not available: 252 Blank: 2.4 + name='respiration_rate', + type=BASE_TYPES[0x83], # sint16 + def_num=1, + scale=100, + units='breaths/min', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 200: MessageType( - name='exd_screen_configuration', - mesg_num=200, + 308: MessageType( # User's current heart rate data used for HSA custom data logging + name='hsa_heart_rate_data', + mesg_num=308, fields={ - 0: Field( - name='screen_index', - type=BASE_TYPES[0x02], # uint8 + 0: Field( # Processing interval length in seconds + name='processing_interval', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='s', ), - 1: Field( # number of fields in screen - name='field_count', + 1: Field( # Status of measurements in buffer - 0 indicates SEARCHING 1 indicates LOCKED + name='status', type=BASE_TYPES[0x02], # uint8 def_num=1, ), - 2: Field( - name='layout', - type=FIELD_TYPES['exd_layout'], + 2: Field( # Beats / min. Blank: 0 + name='heart_rate', + type=BASE_TYPES[0x02], # uint8 def_num=2, + units='bpm', ), - 3: Field( - name='screen_enabled', - type=FIELD_TYPES['bool'], - def_num=3, - ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 201: MessageType( - name='exd_data_field_configuration', - mesg_num=201, + 314: MessageType( # Body battery data used for HSA custom data logging + name='hsa_body_battery_data', + mesg_num=314, fields={ - 0: Field( - name='screen_index', - type=BASE_TYPES[0x02], # uint8 + 0: Field( # Processing interval length in seconds + name='processing_interval', + type=BASE_TYPES[0x84], # uint16 def_num=0, + units='s', ), - 1: Field( - name='concept_field', - type=BASE_TYPES[0x0D], # byte + 1: Field( # Body battery level: [0,100] Blank: -16 + name='level', + type=BASE_TYPES[0x01], # sint8 def_num=1, - components=( - ComponentField( - name='field_id', - def_num=2, - accumulate=False, - bits=4, - bit_offset=0, - ), - ComponentField( - name='concept_count', - def_num=3, - accumulate=False, - bits=4, - bit_offset=4, - ), - ), + units='percent', ), - 2: Field( - name='field_id', - type=BASE_TYPES[0x02], # uint8 + 2: Field( # Body battery charged value + name='charged', + type=BASE_TYPES[0x83], # sint16 def_num=2, ), - 3: Field( - name='concept_count', - type=BASE_TYPES[0x02], # uint8 + 3: Field( # Body battery uncharged value + name='uncharged', + type=BASE_TYPES[0x83], # sint16 def_num=3, ), - 4: Field( - name='display_type', - type=FIELD_TYPES['exd_display_type'], - def_num=4, - ), - 5: Field( - name='title', - type=BASE_TYPES[0x07], # string - def_num=5, - ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 202: MessageType( - name='exd_data_concept_configuration', - mesg_num=202, + 315: MessageType( # HSA events + name='hsa_event', + mesg_num=315, fields={ - 0: Field( - name='screen_index', + 0: Field( # Event ID. Health SDK use only + name='event_id', type=BASE_TYPES[0x02], # uint8 def_num=0, ), - 1: Field( - name='concept_field', - type=BASE_TYPES[0x0D], # byte + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 376: MessageType( + name='hsa_gyroscope_data', + mesg_num=376, + fields={ + 0: Field( # Millisecond resolution of the timestamp + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + units='ms', + ), + 1: Field( # Sampling Interval in 32 kHz timescale + name='sampling_interval', + type=BASE_TYPES[0x84], # uint16 def_num=1, - components=( - ComponentField( - name='field_id', - def_num=2, - accumulate=False, - bits=4, - bit_offset=0, - ), - ComponentField( - name='concept_index', - def_num=3, - accumulate=False, - bits=4, - bit_offset=4, - ), - ), + units='1/32768 s', ), - 2: Field( - name='field_id', - type=BASE_TYPES[0x02], # uint8 + 2: Field( # X-Axis Measurement + name='gyro_x', + type=BASE_TYPES[0x83], # sint16 def_num=2, + scale=28.57143, + units='deg/s', ), - 3: Field( - name='concept_index', - type=BASE_TYPES[0x02], # uint8 + 3: Field( # Y-Axis Measurement + name='gyro_y', + type=BASE_TYPES[0x83], # sint16 def_num=3, + scale=28.57143, + units='deg/s', ), - 4: Field( - name='data_page', - type=BASE_TYPES[0x02], # uint8 + 4: Field( # Z-Axis Measurement + name='gyro_z', + type=BASE_TYPES[0x83], # sint16 def_num=4, + scale=28.57143, + units='deg/s', ), - 5: Field( - name='concept_key', - type=BASE_TYPES[0x02], # uint8 + 5: Field( # 32 kHz timestamp + name='timestamp_32k', + type=BASE_TYPES[0x86], # uint32 def_num=5, + units='1/32768 s', ), - 6: Field( - name='scaling', + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 389: MessageType( # Configuration data for HSA custom data logging + name='hsa_configuration_data', + mesg_num=389, + fields={ + 0: Field( # Encoded configuration data. Health SDK use only + name='data', + type=BASE_TYPES[0x0D], # byte + def_num=0, + ), + 1: Field( # Size in bytes of data field + name='data_size', type=BASE_TYPES[0x02], # uint8 - def_num=6, + def_num=1, ), - 8: Field( - name='data_units', - type=FIELD_TYPES['exd_data_units'], - def_num=8, + 253: FIELD_TYPE_TIMESTAMP, # Encoded configuration data + }, + ), + 409: MessageType( # Wrist temperature data used for HSA custom data logging + name='hsa_wrist_temperature_data', + mesg_num=409, + fields={ + 0: Field( # Processing interval length in seconds + name='processing_interval', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + units='s', ), - 9: Field( - name='qualifier', - type=FIELD_TYPES['exd_qualifiers'], - def_num=9, - ), - 10: Field( - name='descriptor', - type=FIELD_TYPES['exd_descriptors'], - def_num=10, + 1: Field( # Wrist temperature reading + name='value', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + scale=1000, + units='degC', ), - 11: Field( - name='is_signed', - type=FIELD_TYPES['bool'], - def_num=11, + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + + + # ***************************** Other Messages ***************************** + 78: MessageType( # Heart rate variability + name='hrv', + mesg_num=78, + fields={ + 0: Field( # Time between beats + name='time', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + scale=1000, + units='s', ), }, ), - 206: MessageType( # Must be logged before developer field is used - name='field_description', - mesg_num=206, + 80: MessageType( + name='ant_rx', + mesg_num=80, fields={ 0: Field( - name='developer_data_index', - type=BASE_TYPES[0x02], # uint8 + name='fractional_timestamp', + type=BASE_TYPES[0x84], # uint16 def_num=0, + scale=32768, + units='s', ), 1: Field( - name='field_definition_number', - type=BASE_TYPES[0x02], # uint8 + name='mesg_id', + type=BASE_TYPES[0x0D], # byte def_num=1, ), 2: Field( - name='fit_base_type_id', - type=FIELD_TYPES['fit_base_type'], + name='mesg_data', + type=BASE_TYPES[0x0D], # byte def_num=2, + components=( + ComponentField( + name='channel_number', + def_num=3, + accumulate=False, + bits=8, + bit_offset=0, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=8, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=16, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=24, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=32, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=40, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=48, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=56, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=64, + ), + ), ), 3: Field( - name='field_name', - type=BASE_TYPES[0x07], # string + name='channel_number', + type=BASE_TYPES[0x02], # uint8 def_num=3, ), 4: Field( - name='array', - type=BASE_TYPES[0x02], # uint8 + name='data', + type=BASE_TYPES[0x0D], # byte def_num=4, ), - 5: Field( - name='components', - type=BASE_TYPES[0x07], # string - def_num=5, - ), - 6: Field( - name='scale', - type=BASE_TYPES[0x02], # uint8 - def_num=6, - ), - 7: Field( - name='offset', - type=BASE_TYPES[0x01], # sint8 - def_num=7, - ), - 8: Field( - name='units', - type=BASE_TYPES[0x07], # string - def_num=8, - ), - 9: Field( - name='bits', - type=BASE_TYPES[0x07], # string - def_num=9, - ), - 10: Field( - name='accumulate', - type=BASE_TYPES[0x07], # string - def_num=10, - ), - 13: Field( - name='fit_base_unit_id', - type=FIELD_TYPES['fit_base_unit'], - def_num=13, - ), - 14: Field( - name='native_mesg_num', - type=FIELD_TYPES['mesg_num'], - def_num=14, - ), - 15: Field( - name='native_field_num', - type=BASE_TYPES[0x02], # uint8 - def_num=15, - ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 207: MessageType( # Must be logged before field description - name='developer_data_id', - mesg_num=207, + 81: MessageType( + name='ant_tx', + mesg_num=81, fields={ 0: Field( - name='developer_id', - type=BASE_TYPES[0x0D], # byte + name='fractional_timestamp', + type=BASE_TYPES[0x84], # uint16 def_num=0, + scale=32768, + units='s', ), 1: Field( - name='application_id', + name='mesg_id', type=BASE_TYPES[0x0D], # byte def_num=1, ), 2: Field( - name='manufacturer_id', - type=FIELD_TYPES['manufacturer'], + name='mesg_data', + type=BASE_TYPES[0x0D], # byte def_num=2, + components=( + ComponentField( + name='channel_number', + def_num=3, + accumulate=False, + bits=8, + bit_offset=0, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=8, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=16, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=24, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=32, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=40, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=48, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=56, + ), + ComponentField( + name='data', + def_num=4, + accumulate=False, + bits=8, + bit_offset=64, + ), + ), ), 3: Field( - name='developer_data_index', + name='channel_number', type=BASE_TYPES[0x02], # uint8 def_num=3, ), 4: Field( - name='application_version', - type=BASE_TYPES[0x86], # uint32 - def_num=4, + name='data', + type=BASE_TYPES[0x0D], # byte + def_num=4, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 208: MessageType( - name='magnetometer_data', - mesg_num=208, + 82: MessageType( + name='ant_channel_id', + mesg_num=82, fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( + name='channel_number', + type=BASE_TYPES[0x02], # uint8 def_num=0, - units='ms', ), - 1: Field( # Each time in the array describes the time at which the compass sample with the corrosponding index was taken. Limited to 30 samples in each message. The samples may span across seconds. Array size must match the number of samples in cmps_x and cmps_y and cmps_z - name='sample_time_offset', - type=BASE_TYPES[0x84], # uint16 + 1: Field( + name='device_type', + type=BASE_TYPES[0x0A], # uint8z def_num=1, - units='ms', ), - 2: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='mag_x', - type=BASE_TYPES[0x84], # uint16 + 2: Field( + name='device_number', + type=BASE_TYPES[0x8B], # uint16z def_num=2, - units='counts', ), - 3: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='mag_y', - type=BASE_TYPES[0x84], # uint16 + 3: Field( + name='transmission_type', + type=BASE_TYPES[0x0A], # uint8z def_num=3, - units='counts', ), - 4: Field( # These are the raw ADC reading. Maximum number of samples is 30 in each message. The samples may span across seconds. A conversion will need to be done on this data once read. - name='mag_z', - type=BASE_TYPES[0x84], # uint16 + 4: Field( + name='device_index', + type=FIELD_TYPES['device_index'], def_num=4, - units='counts', ), - 5: Field( # Calibrated Magnetometer reading - name='calibrated_mag_x', - type=BASE_TYPES[0x88], # float32 - def_num=5, - units='G', + }, + ), + 145: MessageType( + name='memo_glob', + mesg_num=145, + fields={ + 0: Field( # Deprecated. Use data field. + name='memo', + type=BASE_TYPES[0x0D], # byte + def_num=0, ), - 6: Field( # Calibrated Magnetometer reading - name='calibrated_mag_y', - type=BASE_TYPES[0x88], # float32 - def_num=6, - units='G', + 1: Field( # Message Number of the parent message + name='mesg_num', + type=FIELD_TYPES['mesg_num'], + def_num=1, ), - 7: Field( # Calibrated Magnetometer reading - name='calibrated_mag_z', - type=BASE_TYPES[0x88], # float32 - def_num=7, - units='G', + 2: Field( # Index of mesg that this glob is associated with. + name='parent_index', + type=FIELD_TYPES['message_index'], + def_num=2, + ), + 3: Field( # Field within the parent that this glob is associated with + name='field_num', + type=BASE_TYPES[0x02], # uint8 + def_num=3, + ), + 4: Field( # Block of utf8 bytes. Note, mutltibyte characters may be split across adjoining memo_glob messages. + name='data', + type=BASE_TYPES[0x0A], # uint8z + def_num=4, + ), + 250: Field( # Sequence number of memo blocks + name='part_index', + type=BASE_TYPES[0x86], # uint32 + def_num=250, ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp }, ), - 209: MessageType( - name='barometer_data', - mesg_num=209, + 200: MessageType( + name='exd_screen_configuration', + mesg_num=200, fields={ - 0: Field( # Millisecond part of the timestamp. - name='timestamp_ms', - type=BASE_TYPES[0x84], # uint16 + 0: Field( + name='screen_index', + type=BASE_TYPES[0x02], # uint8 def_num=0, - units='ms', ), - 1: Field( # Each time in the array describes the time at which the barometer sample with the corrosponding index was taken. The samples may span across seconds. Array size must match the number of samples in baro_cal - name='sample_time_offset', - type=BASE_TYPES[0x84], # uint16 + 1: Field( # number of fields in screen + name='field_count', + type=BASE_TYPES[0x02], # uint8 def_num=1, - units='ms', ), - 2: Field( # These are the raw ADC reading. The samples may span across seconds. A conversion will need to be done on this data once read. - name='baro_pres', - type=BASE_TYPES[0x86], # uint32 + 2: Field( + name='layout', + type=FIELD_TYPES['exd_layout'], def_num=2, - units='Pa', ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp + 3: Field( + name='screen_enabled', + type=FIELD_TYPES['bool'], + def_num=3, + ), }, ), - 210: MessageType( - name='one_d_sensor_calibration', - mesg_num=210, + 201: MessageType( + name='exd_data_field_configuration', + mesg_num=201, fields={ - 0: Field( # Indicates which sensor the calibration is for - name='sensor_type', - type=FIELD_TYPES['sensor_type'], + 0: Field( + name='screen_index', + type=BASE_TYPES[0x02], # uint8 def_num=0, ), - 1: Field( # Calibration factor used to convert from raw ADC value to degrees, g, etc. - name='calibration_factor', - type=BASE_TYPES[0x86], # uint32 + 1: Field( + name='concept_field', + type=BASE_TYPES[0x0D], # byte def_num=1, - subfields=( - SubField( # Barometer calibration factor - name='baro_cal_factor', - def_num=1, - type=BASE_TYPES[0x86], # uint32 - units='Pa', - ref_fields=( - ReferenceField( - name='sensor_type', - def_num=0, - value='barometer', - raw_value=3, - ), - ), + components=( + ComponentField( + name='field_id', + def_num=2, + accumulate=False, + bits=4, + bit_offset=0, + ), + ComponentField( + name='concept_count', + def_num=3, + accumulate=False, + bits=4, + bit_offset=4, ), ), ), - 2: Field( # Calibration factor divisor - name='calibration_divisor', - type=BASE_TYPES[0x86], # uint32 + 2: Field( + name='field_id', + type=BASE_TYPES[0x02], # uint8 def_num=2, - units='counts', ), - 3: Field( # Level shift value used to shift the ADC value back into range - name='level_shift', - type=BASE_TYPES[0x86], # uint32 + 3: Field( + name='concept_count', + type=BASE_TYPES[0x02], # uint8 def_num=3, ), - 4: Field( # Internal Calibration factor - name='offset_cal', - type=BASE_TYPES[0x85], # sint32 + 4: Field( + name='display_type', + type=FIELD_TYPES['exd_display_type'], def_num=4, ), - 253: FIELD_TYPE_TIMESTAMP, # Whole second part of the timestamp + 5: Field( + name='title', + type=BASE_TYPES[0x07], # string + def_num=5, + ), }, ), - 225: MessageType( - name='set', - mesg_num=225, + 202: MessageType( + name='exd_data_concept_configuration', + mesg_num=202, fields={ 0: Field( - name='duration', - type=BASE_TYPES[0x86], # uint32 + name='screen_index', + type=BASE_TYPES[0x02], # uint8 def_num=0, - scale=1000, - units='s', ), - 3: Field( # # of repitions of the movement - name='repetitions', - type=BASE_TYPES[0x84], # uint16 + 1: Field( + name='concept_field', + type=BASE_TYPES[0x0D], # byte + def_num=1, + components=( + ComponentField( + name='field_id', + def_num=2, + accumulate=False, + bits=4, + bit_offset=0, + ), + ComponentField( + name='concept_index', + def_num=3, + accumulate=False, + bits=4, + bit_offset=4, + ), + ), + ), + 2: Field( + name='field_id', + type=BASE_TYPES[0x02], # uint8 + def_num=2, + ), + 3: Field( + name='concept_index', + type=BASE_TYPES[0x02], # uint8 def_num=3, ), - 4: Field( # Amount of weight applied for the set - name='weight', - type=BASE_TYPES[0x84], # uint16 + 4: Field( + name='data_page', + type=BASE_TYPES[0x02], # uint8 def_num=4, - scale=16, - units='kg', ), 5: Field( - name='set_type', - type=FIELD_TYPES['set_type'], + name='concept_key', + type=BASE_TYPES[0x02], # uint8 def_num=5, ), - 6: Field( # Start time of the set - name='start_time', - type=FIELD_TYPES['date_time'], + 6: Field( + name='scaling', + type=BASE_TYPES[0x02], # uint8 def_num=6, ), - 7: Field( - name='category', - type=FIELD_TYPES['exercise_category'], - def_num=7, - ), - 8: Field( # Based on the associated category, see [category]_exercise_names - name='category_subtype', - type=BASE_TYPES[0x84], # uint16 + 8: Field( + name='data_units', + type=FIELD_TYPES['exd_data_units'], def_num=8, ), 9: Field( - name='weight_display_unit', - type=FIELD_TYPES['fit_base_unit'], + name='qualifier', + type=FIELD_TYPES['exd_qualifiers'], def_num=9, ), 10: Field( - name='message_index', - type=FIELD_TYPES['message_index'], + name='descriptor', + type=FIELD_TYPES['exd_descriptors'], def_num=10, ), 11: Field( - name='wkt_step_index', - type=FIELD_TYPES['message_index'], + name='is_signed', + type=FIELD_TYPES['bool'], def_num=11, ), - 254: Field( # Timestamp of the set - name='timestamp', - type=FIELD_TYPES['date_time'], - def_num=254, - ), - }, - ), - 227: MessageType( # Value from 1 to 100 calculated by FirstBeat - name='stress_level', - mesg_num=227, - fields={ - 0: Field( - name='stress_level_value', - type=BASE_TYPES[0x83], # sint16 - def_num=0, - ), - 1: Field( # Time stress score was calculated - name='stress_level_time', - type=FIELD_TYPES['date_time'], - def_num=1, - units='s', - ), }, ), - 258: MessageType( - name='dive_settings', - mesg_num=258, + 268: MessageType( + name='dive_summary', + mesg_num=268, fields={ 0: Field( - name='name', - type=BASE_TYPES[0x07], # string + name='reference_mesg', + type=FIELD_TYPES['mesg_num'], def_num=0, ), 1: Field( - name='model', - type=FIELD_TYPES['tissue_model_type'], + name='reference_index', + type=FIELD_TYPES['message_index'], def_num=1, ), - 2: Field( - name='gf_low', - type=BASE_TYPES[0x02], # uint8 + 2: Field( # 0 if above water + name='avg_depth', + type=BASE_TYPES[0x86], # uint32 def_num=2, - units='percent', + scale=1000, + units='m', ), - 3: Field( - name='gf_high', - type=BASE_TYPES[0x02], # uint8 + 3: Field( # 0 if above water + name='max_depth', + type=BASE_TYPES[0x86], # uint32 def_num=3, - units='percent', + scale=1000, + units='m', ), - 4: Field( - name='water_type', - type=FIELD_TYPES['water_type'], + 4: Field( # Time since end of last dive + name='surface_interval', + type=BASE_TYPES[0x86], # uint32 def_num=4, + units='s', ), - 5: Field( # Fresh water is usually 1000; salt water is usually 1025 - name='water_density', - type=BASE_TYPES[0x88], # float32 + 5: Field( + name='start_cns', + type=BASE_TYPES[0x02], # uint8 def_num=5, - units='kg/m^3', + units='percent', ), - 6: Field( # Typically 1.40 - name='po2_warn', + 6: Field( + name='end_cns', type=BASE_TYPES[0x02], # uint8 def_num=6, - scale=100, units='percent', ), - 7: Field( # Typically 1.60 - name='po2_critical', - type=BASE_TYPES[0x02], # uint8 + 7: Field( + name='start_n2', + type=BASE_TYPES[0x84], # uint16 def_num=7, - scale=100, units='percent', ), 8: Field( - name='po2_deco', - type=BASE_TYPES[0x02], # uint8 + name='end_n2', + type=BASE_TYPES[0x84], # uint16 def_num=8, - scale=100, units='percent', ), 9: Field( - name='safety_stop_enabled', - type=FIELD_TYPES['bool'], + name='o2_toxicity', + type=BASE_TYPES[0x84], # uint16 def_num=9, + units='OTUs', ), 10: Field( - name='bottom_depth', - type=BASE_TYPES[0x88], # float32 + name='dive_number', + type=BASE_TYPES[0x86], # uint32 def_num=10, ), 11: Field( name='bottom_time', type=BASE_TYPES[0x86], # uint32 def_num=11, + scale=1000, + units='s', ), - 12: Field( - name='apnea_countdown_enabled', - type=FIELD_TYPES['bool'], + 12: Field( # Average pressure-based surface air consumption + name='avg_pressure_sac', + type=BASE_TYPES[0x84], # uint16 def_num=12, + scale=100, + units='bar/min', ), - 13: Field( - name='apnea_countdown_time', - type=BASE_TYPES[0x86], # uint32 + 13: Field( # Average volumetric surface air consumption + name='avg_volume_sac', + type=BASE_TYPES[0x84], # uint16 def_num=13, + scale=100, + units='L/min', ), - 14: Field( - name='backlight_mode', - type=FIELD_TYPES['dive_backlight_mode'], + 14: Field( # Average respiratory minute volume + name='avg_rmv', + type=BASE_TYPES[0x84], # uint16 def_num=14, + scale=100, + units='L/min', ), - 15: Field( - name='backlight_brightness', - type=BASE_TYPES[0x02], # uint8 + 15: Field( # Time to reach deepest level stop + name='descent_time', + type=BASE_TYPES[0x86], # uint32 def_num=15, + scale=1000, + units='s', ), - 16: Field( - name='backlight_timeout', - type=FIELD_TYPES['backlight_timeout'], + 16: Field( # Time after leaving bottom until reaching surface + name='ascent_time', + type=BASE_TYPES[0x86], # uint32 def_num=16, + scale=1000, + units='s', ), - 17: Field( # Time between surfacing and ending the activity - name='repeat_dive_interval', - type=BASE_TYPES[0x84], # uint16 + 17: Field( # Average ascent rate, not including descents or stops + name='avg_ascent_rate', + type=BASE_TYPES[0x85], # sint32 def_num=17, - units='s', + scale=1000, + units='m/s', ), - 18: Field( # Time at safety stop (if enabled) - name='safety_stop_time', - type=BASE_TYPES[0x84], # uint16 - def_num=18, - units='s', + 22: Field( # Average descent rate, not including ascents or stops + name='avg_descent_rate', + type=BASE_TYPES[0x86], # uint32 + def_num=22, + scale=1000, + units='m/s', ), - 19: Field( - name='heart_rate_source_type', - type=FIELD_TYPES['source_type'], - def_num=19, + 23: Field( # Maximum ascent rate + name='max_ascent_rate', + type=BASE_TYPES[0x86], # uint32 + def_num=23, + scale=1000, + units='m/s', ), - 20: Field( - name='heart_rate_source', - type=BASE_TYPES[0x02], # uint8 - def_num=20, - subfields=( - SubField( - name='heart_rate_antplus_device_type', - def_num=20, - type=FIELD_TYPES['antplus_device_type'], - ref_fields=( - ReferenceField( - name='heart_rate_source_type', - def_num=19, - value='antplus', - raw_value=1, - ), - ), - ), - SubField( - name='heart_rate_local_device_type', - def_num=20, - type=FIELD_TYPES['local_device_type'], - ref_fields=( - ReferenceField( - name='heart_rate_source_type', - def_num=19, - value='local', - raw_value=5, - ), - ), - ), - ), + 24: Field( # Maximum descent rate + name='max_descent_rate', + type=BASE_TYPES[0x86], # uint32 + def_num=24, + scale=1000, + units='m/s', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 25: Field( # Time spent neither ascending nor descending + name='hang_time', + type=BASE_TYPES[0x86], # uint32 + def_num=25, + scale=1000, + units='s', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 259: MessageType( - name='dive_gas', - mesg_num=259, + 275: MessageType( + name='sleep_level', + mesg_num=275, fields={ 0: Field( - name='helium_content', - type=BASE_TYPES[0x02], # uint8 + name='sleep_level', + type=FIELD_TYPES['sleep_level'], def_num=0, - units='percent', - ), - 1: Field( - name='oxygen_content', - type=BASE_TYPES[0x02], # uint8 - def_num=1, - units='percent', - ), - 2: Field( - name='status', - type=FIELD_TYPES['dive_gas_status'], - def_num=2, - ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 262: MessageType( - name='dive_alarm', - mesg_num=262, + 289: MessageType( # Number of acclerometer zero crossings summed over the specified time interval + name='aad_accel_features', + mesg_num=289, fields={ - 0: Field( - name='depth', - type=BASE_TYPES[0x86], # uint32 + 0: Field( # Time interval length in seconds + name='time', + type=BASE_TYPES[0x84], # uint16 def_num=0, - scale=1000, - units='m', + units='s', ), - 1: Field( - name='time', - type=BASE_TYPES[0x85], # sint32 + 1: Field( # Total accelerometer energy in the interval + name='energy_total', + type=BASE_TYPES[0x86], # uint32 def_num=1, - units='s', ), - 2: Field( - name='enabled', - type=FIELD_TYPES['bool'], + 2: Field( # Count of zero crossings + name='zero_cross_cnt', + type=BASE_TYPES[0x84], # uint16 def_num=2, ), - 3: Field( - name='alarm_type', - type=FIELD_TYPES['dive_alarm_type'], + 3: Field( # Instance ID of zero crossing algorithm + name='instance', + type=BASE_TYPES[0x02], # uint8 def_num=3, ), - 4: Field( - name='sound', - type=FIELD_TYPES['tone'], + 4: Field( # Total accelerometer time above threshold in the interval + name='time_above_threshold', + type=BASE_TYPES[0x84], # uint16 def_num=4, + scale=25, + units='s', ), - 5: Field( - name='dive_types', - type=FIELD_TYPES['sub_sport'], - def_num=5, + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 290: MessageType( # Array of heart beat intervals + name='beat_intervals', + mesg_num=290, + fields={ + 0: Field( # Milliseconds past date_time + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + units='ms', ), - 254: Field( # Index of the alarm - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 1: Field( # Array of millisecond times between beats + name='time', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + units='ms', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 264: MessageType( - name='exercise_title', - mesg_num=264, + 297: MessageType( + name='respiration_rate', + mesg_num=297, + fields={ + 0: Field( # Breaths * 100 /min, -300 indicates invalid, -200 indicates large motion, -100 indicates off wrist + name='respiration_rate', + type=BASE_TYPES[0x83], # sint16 + def_num=0, + scale=100, + units='breaths/min', + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 319: MessageType( + name='tank_update', + mesg_num=319, fields={ 0: Field( - name='exercise_category', - type=FIELD_TYPES['exercise_category'], + name='sensor', + type=FIELD_TYPES['ant_channel_id'], def_num=0, ), 1: Field( - name='exercise_name', + name='pressure', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + scale=100, + units='bar', + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 323: MessageType( + name='tank_summary', + mesg_num=323, + fields={ + 0: Field( + name='sensor', + type=FIELD_TYPES['ant_channel_id'], + def_num=0, + ), + 1: Field( + name='start_pressure', type=BASE_TYPES[0x84], # uint16 def_num=1, + scale=100, + units='bar', ), 2: Field( - name='wkt_step_name', - type=BASE_TYPES[0x07], # string + name='end_pressure', + type=BASE_TYPES[0x84], # uint16 def_num=2, + scale=100, + units='bar', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 3: Field( + name='volume_used', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + scale=100, + units='L', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - 268: MessageType( - name='dive_summary', - mesg_num=268, + 346: MessageType( + name='sleep_assessment', + mesg_num=346, fields={ - 0: Field( - name='reference_mesg', - type=FIELD_TYPES['mesg_num'], + 0: Field( # Average of awake_time_score and awakenings_count_score. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='combined_awake_score', + type=BASE_TYPES[0x02], # uint8 def_num=0, ), - 1: Field( - name='reference_index', - type=FIELD_TYPES['message_index'], + 1: Field( # Score that evaluates the total time spent awake between sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='awake_time_score', + type=BASE_TYPES[0x02], # uint8 def_num=1, ), - 2: Field( # 0 if above water - name='avg_depth', - type=BASE_TYPES[0x86], # uint32 + 2: Field( # Score that evaluates the number of awakenings that interrupt sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='awakenings_count_score', + type=BASE_TYPES[0x02], # uint8 def_num=2, - scale=1000, - units='m', ), - 3: Field( # 0 if above water - name='max_depth', - type=BASE_TYPES[0x86], # uint32 + 3: Field( # Score that evaluates the amount of deep sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='deep_sleep_score', + type=BASE_TYPES[0x02], # uint8 def_num=3, - scale=1000, - units='m', ), - 4: Field( # Time since end of last dive - name='surface_interval', - type=BASE_TYPES[0x86], # uint32 + 4: Field( # Score that evaluates the quality of sleep based on sleep stages, heart-rate variability and possible awakenings during the night. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='sleep_duration_score', + type=BASE_TYPES[0x02], # uint8 def_num=4, - units='s', ), - 5: Field( - name='start_cns', + 5: Field( # Score that evaluates the amount of light sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='light_sleep_score', type=BASE_TYPES[0x02], # uint8 def_num=5, - units='percent', ), - 6: Field( - name='end_cns', + 6: Field( # Total score that summarizes the overall quality of sleep, combining sleep duration and quality. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='overall_sleep_score', type=BASE_TYPES[0x02], # uint8 def_num=6, - units='percent', ), - 7: Field( - name='start_n2', - type=BASE_TYPES[0x84], # uint16 + 7: Field( # Score that evaluates the quality of sleep based on sleep stages, heart-rate variability and possible awakenings during the night. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='sleep_quality_score', + type=BASE_TYPES[0x02], # uint8 def_num=7, - units='percent', ), - 8: Field( - name='end_n2', - type=BASE_TYPES[0x84], # uint16 + 8: Field( # Score that evaluates stress and recovery during sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='sleep_recovery_score', + type=BASE_TYPES[0x02], # uint8 def_num=8, - units='percent', ), - 9: Field( - name='o2_toxicity', - type=BASE_TYPES[0x84], # uint16 + 9: Field( # Score that evaluates the amount of REM sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='rem_sleep_score', + type=BASE_TYPES[0x02], # uint8 def_num=9, - units='OTUs', ), - 10: Field( - name='dive_number', - type=BASE_TYPES[0x86], # uint32 + 10: Field( # Score that evaluates the amount of restlessness during sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='sleep_restlessness_score', + type=BASE_TYPES[0x02], # uint8 def_num=10, ), - 11: Field( - name='bottom_time', - type=BASE_TYPES[0x86], # uint32 + 11: Field( # The number of awakenings during sleep. + name='awakenings_count', + type=BASE_TYPES[0x02], # uint8 def_num=11, - scale=1000, - units='s', ), - 253: FIELD_TYPE_TIMESTAMP, - }, - ), - - - # ************************* Activity File Messages ************************* - 34: MessageType( - name='activity', - mesg_num=34, - fields={ - 0: Field( # Exclude pauses - name='total_timer_time', - type=BASE_TYPES[0x86], # uint32 - def_num=0, - scale=1000, - units='s', + 14: Field( # Score that evaluates the sleep interruptions. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID. + name='interruptions_score', + type=BASE_TYPES[0x02], # uint8 + def_num=14, ), - 1: Field( - name='num_sessions', + 15: Field( # Excludes stress during awake periods in the sleep window + name='average_stress_during_sleep', type=BASE_TYPES[0x84], # uint16 - def_num=1, - ), - 2: Field( - name='type', - type=FIELD_TYPES['activity'], - def_num=2, - ), - 3: Field( - name='event', - type=FIELD_TYPES['event'], - def_num=3, - ), - 4: Field( - name='event_type', - type=FIELD_TYPES['event_type'], - def_num=4, - ), - 5: Field( # timestamp epoch expressed in local time, used to convert activity timestamps to local time - name='local_timestamp', - type=FIELD_TYPES['local_date_time'], - def_num=5, - ), - 6: Field( - name='event_group', - type=BASE_TYPES[0x02], # uint8 - def_num=6, + def_num=15, + scale=100, ), - 253: FIELD_TYPE_TIMESTAMP, }, ), - - - # ********************** Blood Pressure File Messages ********************** - 51: MessageType( - name='blood_pressure', - mesg_num=51, + 370: MessageType( + name='hrv_status_summary', + mesg_num=370, fields={ - 0: Field( - name='systolic_pressure', + 0: Field( # 7 day RMSSD average over sleep + name='weekly_average', type=BASE_TYPES[0x84], # uint16 def_num=0, - units='mmHg', + scale=128, + units='ms', ), - 1: Field( - name='diastolic_pressure', + 1: Field( # Last night RMSSD average over sleep + name='last_night_average', type=BASE_TYPES[0x84], # uint16 def_num=1, - units='mmHg', + scale=128, + units='ms', ), - 2: Field( - name='mean_arterial_pressure', + 2: Field( # 5 minute high RMSSD value over sleep + name='last_night_5_min_high', type=BASE_TYPES[0x84], # uint16 def_num=2, - units='mmHg', + scale=128, + units='ms', ), - 3: Field( - name='map_3_sample_mean', + 3: Field( # 3 week baseline, upper boundary of low HRV status + name='baseline_low_upper', type=BASE_TYPES[0x84], # uint16 def_num=3, - units='mmHg', + scale=128, + units='ms', ), - 4: Field( - name='map_morning_values', + 4: Field( # 3 week baseline, lower boundary of balanced HRV status + name='baseline_balanced_lower', type=BASE_TYPES[0x84], # uint16 def_num=4, - units='mmHg', + scale=128, + units='ms', ), - 5: Field( - name='map_evening_values', + 5: Field( # 3 week baseline, upper boundary of balanced HRV status + name='baseline_balanced_upper', type=BASE_TYPES[0x84], # uint16 def_num=5, - units='mmHg', + scale=128, + units='ms', ), 6: Field( - name='heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=6, - units='bpm', - ), - 7: Field( - name='heart_rate_type', - type=FIELD_TYPES['hr_type'], - def_num=7, - ), - 8: Field( name='status', - type=FIELD_TYPES['bp_status'], - def_num=8, + type=FIELD_TYPES['hrv_status'], + def_num=6, ), - 9: Field( # Associates this blood pressure message to a user. This corresponds to the index of the user profile message in the blood pressure file. - name='user_profile_index', - type=FIELD_TYPES['message_index'], - def_num=9, + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 371: MessageType( + name='hrv_value', + mesg_num=371, + fields={ + 0: Field( # 5 minute RMSSD + name='value', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + scale=128, + units='ms', ), 253: FIELD_TYPE_TIMESTAMP, }, ), - - - # ************************** Course File Messages ************************** - 31: MessageType( - name='course', - mesg_num=31, + 372: MessageType( # Raw Beat-to-Beat Interval values + name='raw_bbi', + mesg_num=372, fields={ - 4: Field( - name='sport', - type=FIELD_TYPES['sport'], - def_num=4, + 0: Field( # Millisecond resolution of the timestamp + name='timestamp_ms', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + units='ms', ), - 5: Field( - name='name', - type=BASE_TYPES[0x07], # string - def_num=5, - ), - 6: Field( - name='capabilities', - type=FIELD_TYPES['course_capabilities'], - def_num=6, - ), - 7: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], - def_num=7, + 1: Field( # 1 bit for gap indicator, 1 bit for quality indicator, and 14 bits for Beat-to-Beat interval values in whole-integer millisecond resolution + name='data', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + components=( + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=0, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=14, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=15, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=16, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=30, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=31, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=32, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=46, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=47, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=48, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=62, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=63, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=64, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=78, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=79, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=80, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=94, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=95, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=96, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=110, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=111, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=112, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=126, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=127, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=128, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=142, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=143, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=144, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=158, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=159, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=160, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=174, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=175, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=176, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=190, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=191, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=192, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=206, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=207, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=208, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=222, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=223, + ), + ComponentField( + name='time', + def_num=2, + accumulate=False, + bits=14, + bit_offset=224, + ), + ComponentField( + name='quality', + def_num=3, + accumulate=False, + bits=1, + bit_offset=238, + ), + ComponentField( + name='gap', + def_num=4, + accumulate=False, + bits=1, + bit_offset=239, + ), + ), ), - }, - ), - - - # ************************** Device File Messages ************************** - 35: MessageType( - name='software', - mesg_num=35, - fields={ - 3: Field( - name='version', + 2: Field( # Array of millisecond times between beats + name='time', type=BASE_TYPES[0x84], # uint16 - def_num=3, - scale=100, + def_num=2, + units='ms', ), - 5: Field( - name='part_number', - type=BASE_TYPES[0x07], # string - def_num=5, + 3: Field( # 1 = high confidence. 0 = low confidence. N/A when gap = 1 + name='quality', + type=BASE_TYPES[0x02], # uint8 + def_num=3, ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + 4: Field( # 1 = gap (time represents ms gap length). 0 = BBI data + name='gap', + type=BASE_TYPES[0x02], # uint8 + def_num=4, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - - - # ************************** Goals File Messages *************************** - 15: MessageType( - name='goal', - mesg_num=15, + 387: MessageType( # Specifically used for XERO products. + name='chrono_shot_session', + mesg_num=387, fields={ 0: Field( - name='sport', - type=FIELD_TYPES['sport'], + name='min_speed', + type=BASE_TYPES[0x86], # uint32 def_num=0, + scale=1000, + units='m/s', ), 1: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], + name='max_speed', + type=BASE_TYPES[0x86], # uint32 def_num=1, + scale=1000, + units='m/s', ), 2: Field( - name='start_date', - type=FIELD_TYPES['date_time'], + name='avg_speed', + type=BASE_TYPES[0x86], # uint32 def_num=2, + scale=1000, + units='m/s', ), 3: Field( - name='end_date', - type=FIELD_TYPES['date_time'], + name='shot_count', + type=BASE_TYPES[0x84], # uint16 def_num=3, ), 4: Field( - name='type', - type=FIELD_TYPES['goal'], + name='projectile_type', + type=FIELD_TYPES['projectile_type'], def_num=4, ), 5: Field( - name='value', + name='grain_weight', type=BASE_TYPES[0x86], # uint32 def_num=5, + scale=10, + units='gr', ), 6: Field( - name='repeat', - type=FIELD_TYPES['bool'], - def_num=6, - ), - 7: Field( - name='target_value', + name='standard_deviation', type=BASE_TYPES[0x86], # uint32 - def_num=7, - ), - 8: Field( - name='recurrence', - type=FIELD_TYPES['goal_recurrence'], - def_num=8, - ), - 9: Field( - name='recurrence_value', - type=BASE_TYPES[0x84], # uint16 - def_num=9, - ), - 10: Field( - name='enabled', - type=FIELD_TYPES['bool'], - def_num=10, - ), - 11: Field( - name='source', - type=FIELD_TYPES['goal_source'], - def_num=11, - ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, + def_num=6, + scale=1000, + units='m/s', ), + 253: FIELD_TYPE_TIMESTAMP, }, ), - - - # ************************ Monitoring File Messages ************************ - 103: MessageType( - name='monitoring_info', - mesg_num=103, + 388: MessageType( # Specifically used for XERO products. + name='chrono_shot_data', + mesg_num=388, fields={ - 0: Field( # Use to convert activity timestamps to local time if device does not support time zone and daylight savings time correction. - name='local_timestamp', - type=FIELD_TYPES['local_date_time'], + 0: Field( + name='shot_speed', + type=BASE_TYPES[0x86], # uint32 def_num=0, - units='s', + scale=1000, + units='m/s', ), 1: Field( - name='activity_type', - type=FIELD_TYPES['activity_type'], - def_num=1, - ), - 3: Field( # Indexed by activity_type - name='cycles_to_distance', - type=BASE_TYPES[0x84], # uint16 - def_num=3, - scale=5000, - units='m/cycle', - ), - 4: Field( # Indexed by activity_type - name='cycles_to_calories', - type=BASE_TYPES[0x84], # uint16 - def_num=4, - scale=5000, - units='kcal/cycle', - ), - 5: Field( - name='resting_metabolic_rate', + name='shot_num', type=BASE_TYPES[0x84], # uint16 - def_num=5, - units='kcal/day', + def_num=1, ), 253: FIELD_TYPE_TIMESTAMP, }, ), - - - # ***************************** Other Messages ***************************** - 145: MessageType( - name='memo_glob', - mesg_num=145, + 398: MessageType( + name='skin_temp_overnight', + mesg_num=398, fields={ - 0: Field( # Block of utf8 bytes - name='memo', - type=BASE_TYPES[0x0D], # byte + 0: Field( + name='local_timestamp', + type=FIELD_TYPES['local_date_time'], def_num=0, ), - 1: Field( # Allows relating glob to another mesg If used only required for first part of each memo_glob - name='message_number', - type=BASE_TYPES[0x84], # uint16 + 1: Field( # The average overnight deviation from baseline temperature in degrees C + name='average_deviation', + type=BASE_TYPES[0x88], # float32 def_num=1, ), - 2: Field( # Index of external mesg - name='message_index', - type=FIELD_TYPES['message_index'], + 2: Field( # The average 7 day overnight deviation from baseline temperature in degrees C + name='average_7_day_deviation', + type=BASE_TYPES[0x88], # float32 def_num=2, ), - 250: Field( # Sequence number of memo blocks - name='part_index', - type=BASE_TYPES[0x86], # uint32 - def_num=250, + 4: Field( # Final overnight temperature value + name='nightly_value', + type=BASE_TYPES[0x88], # float32 + def_num=4, ), + 253: FIELD_TYPE_TIMESTAMP, }, ), @@ -11468,6 +13332,19 @@ type=BASE_TYPES[0x84], # uint16 def_num=1, subfields=( + SubField( + name='favero_product', + def_num=1, + type=FIELD_TYPES['favero_product'], + ref_fields=( + ReferenceField( + name='manufacturer', + def_num=0, + value='favero_electronics', + raw_value=263, + ), + ), + ), SubField( name='garmin_product', def_num=1, @@ -11491,18 +13368,11 @@ value='dynastream_oem', raw_value=13, ), - ), - ), - SubField( - name='strava_product', - def_num=1, - type=FIELD_TYPES['strava_product'], - ref_fields=( ReferenceField( name='manufacturer', def_num=0, - value='strava', - raw_value=265, + value='tacx', + raw_value=89, ), ), ), @@ -11538,491 +13408,3211 @@ # ************************* Segment File Messages ************************** - 148: MessageType( # Unique Identification data for a segment file - name='segment_id', - mesg_num=148, + 142: MessageType( + name='segment_lap', + mesg_num=142, fields={ - 0: Field( # Friendly name assigned to segment - name='name', - type=BASE_TYPES[0x07], # string + 0: Field( + name='event', + type=FIELD_TYPES['event'], def_num=0, ), - 1: Field( # UUID of the segment - name='uuid', - type=BASE_TYPES[0x07], # string + 1: Field( + name='event_type', + type=FIELD_TYPES['event_type'], def_num=1, ), - 2: Field( # Sport associated with the segment - name='sport', - type=FIELD_TYPES['sport'], + 2: Field( + name='start_time', + type=FIELD_TYPES['date_time'], def_num=2, ), - 3: Field( # Segment enabled for evaluation - name='enabled', - type=FIELD_TYPES['bool'], + 3: Field( + name='start_position_lat', + type=BASE_TYPES[0x85], # sint32 def_num=3, + units='semicircles', ), - 4: Field( # Primary key of the user that created the segment - name='user_profile_primary_key', - type=BASE_TYPES[0x86], # uint32 + 4: Field( + name='start_position_long', + type=BASE_TYPES[0x85], # sint32 def_num=4, + units='semicircles', ), - 5: Field( # ID of the device that created the segment - name='device_id', - type=BASE_TYPES[0x86], # uint32 + 5: Field( + name='end_position_lat', + type=BASE_TYPES[0x85], # sint32 def_num=5, + units='semicircles', ), - 6: Field( # Index for the Leader Board entry selected as the default race participant - name='default_race_leader', - type=BASE_TYPES[0x02], # uint8 + 6: Field( + name='end_position_long', + type=BASE_TYPES[0x85], # sint32 def_num=6, + units='semicircles', ), - 7: Field( # Indicates if any segments should be deleted - name='delete_status', - type=FIELD_TYPES['segment_delete_status'], - def_num=7, - ), - 8: Field( # Indicates how the segment was selected to be sent to the device - name='selection_type', - type=FIELD_TYPES['segment_selection_type'], - def_num=8, - ), - }, - ), - - - # *********************** Segment List File Messages *********************** - 151: MessageType( # Summary of the unique segment and leaderboard information associated with a segment file. This message is used to compile a segment list file describing all segment files on a device. The segment list file is used when refreshing the contents of a segment file with the latest available leaderboard information. - name='segment_file', - mesg_num=151, - fields={ - 1: Field( # UUID of the segment file - name='file_uuid', - type=BASE_TYPES[0x07], # string - def_num=1, - ), - 3: Field( # Enabled state of the segment file - name='enabled', - type=FIELD_TYPES['bool'], - def_num=3, - ), - 4: Field( # Primary key of the user that created the segment file - name='user_profile_primary_key', + 7: Field( # Time (includes pauses) + name='total_elapsed_time', type=BASE_TYPES[0x86], # uint32 - def_num=4, - ), - 7: Field( # Leader type of each leader in the segment file - name='leader_type', - type=FIELD_TYPES['segment_leaderboard_type'], def_num=7, + scale=1000, + units='s', ), - 8: Field( # Group primary key of each leader in the segment file - name='leader_group_primary_key', + 8: Field( # Timer Time (excludes pauses) + name='total_timer_time', type=BASE_TYPES[0x86], # uint32 def_num=8, + scale=1000, + units='s', ), - 9: Field( # Activity ID of each leader in the segment file - name='leader_activity_id', + 9: Field( + name='total_distance', type=BASE_TYPES[0x86], # uint32 def_num=9, + scale=100, + units='m', ), - 10: Field( # String version of the activity ID of each leader in the segment file. 21 characters long for each ID, express in decimal - name='leader_activity_id_string', - type=BASE_TYPES[0x07], # string + 10: Field( + name='total_cycles', + type=BASE_TYPES[0x86], # uint32 def_num=10, + units='cycles', + subfields=( + SubField( + name='total_strokes', + def_num=10, + type=BASE_TYPES[0x86], # uint32 + units='strokes', + ref_fields=( + ReferenceField( + name='sport', + def_num=23, + value='cycling', + raw_value=2, + ), + ), + ), + ), ), - 11: Field( # Index for the Leader Board entry selected as the default race participant - name='default_race_leader', - type=BASE_TYPES[0x02], # uint8 + 11: Field( + name='total_calories', + type=BASE_TYPES[0x84], # uint16 def_num=11, + units='kcal', ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, - ), - }, - ), - - - # ************************* Settings File Messages ************************* - 2: MessageType( - name='device_settings', - mesg_num=2, - fields={ - 0: Field( # Index into time zone arrays. - name='active_time_zone', - type=BASE_TYPES[0x02], # uint8 - def_num=0, - ), - 1: Field( # Offset from system time. Required to convert timestamp from system time to UTC. - name='utc_offset', - type=BASE_TYPES[0x86], # uint32 - def_num=1, - ), - 2: Field( # Offset from system time. - name='time_offset', - type=BASE_TYPES[0x86], # uint32 - def_num=2, - units='s', - ), - 4: Field( # Display mode for the time - name='time_mode', - type=FIELD_TYPES['time_mode'], - def_num=4, - ), - 5: Field( # timezone offset in 1/4 hour increments - name='time_zone_offset', - type=BASE_TYPES[0x01], # sint8 - def_num=5, - scale=4, - units='hr', - ), - 12: Field( # Mode for backlight - name='backlight_mode', - type=FIELD_TYPES['backlight_mode'], + 12: Field( # If New Leaf + name='total_fat_calories', + type=BASE_TYPES[0x84], # uint16 def_num=12, + units='kcal', ), - 36: Field( # Enabled state of the activity tracker functionality - name='activity_tracker_enabled', - type=FIELD_TYPES['bool'], - def_num=36, - ), - 39: Field( # UTC timestamp used to set the devices clock and date - name='clock_time', - type=FIELD_TYPES['date_time'], - def_num=39, + 13: Field( + name='avg_speed', + type=BASE_TYPES[0x84], # uint16 + def_num=13, + scale=1000, + units='m/s', ), - 40: Field( # Bitfield to configure enabled screens for each supported loop - name='pages_enabled', + 14: Field( + name='max_speed', type=BASE_TYPES[0x84], # uint16 - def_num=40, + def_num=14, + scale=1000, + units='m/s', ), - 46: Field( # Enabled state of the move alert - name='move_alert_enabled', - type=FIELD_TYPES['bool'], - def_num=46, + 15: Field( + name='avg_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=15, + units='bpm', ), - 47: Field( # Display mode for the date - name='date_mode', - type=FIELD_TYPES['date_mode'], - def_num=47, + 16: Field( + name='max_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=16, + units='bpm', ), - 55: Field( - name='display_orientation', - type=FIELD_TYPES['display_orientation'], - def_num=55, + 17: Field( # total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time + name='avg_cadence', + type=BASE_TYPES[0x02], # uint8 + def_num=17, + units='rpm', ), - 56: Field( - name='mounting_side', - type=FIELD_TYPES['side'], - def_num=56, + 18: Field( + name='max_cadence', + type=BASE_TYPES[0x02], # uint8 + def_num=18, + units='rpm', ), - 57: Field( # Bitfield to indicate one page as default for each supported loop - name='default_page', + 19: Field( # total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time + name='avg_power', type=BASE_TYPES[0x84], # uint16 - def_num=57, + def_num=19, + units='watts', ), - 58: Field( # Minimum steps before an autosync can occur - name='autosync_min_steps', + 20: Field( + name='max_power', type=BASE_TYPES[0x84], # uint16 - def_num=58, - units='steps', + def_num=20, + units='watts', ), - 59: Field( # Minimum minutes before an autosync can occur - name='autosync_min_time', + 21: Field( + name='total_ascent', type=BASE_TYPES[0x84], # uint16 - def_num=59, - units='minutes', + def_num=21, + units='m', ), - 80: Field( # Enable auto-detect setting for the lactate threshold feature. - name='lactate_threshold_autodetect_enabled', - type=FIELD_TYPES['bool'], - def_num=80, + 22: Field( + name='total_descent', + type=BASE_TYPES[0x84], # uint16 + def_num=22, + units='m', ), - 86: Field( # Automatically upload using BLE - name='ble_auto_upload_enabled', - type=FIELD_TYPES['bool'], - def_num=86, + 23: Field( + name='sport', + type=FIELD_TYPES['sport'], + def_num=23, ), - 89: Field( # Helps to conserve battery by changing modes - name='auto_sync_frequency', - type=FIELD_TYPES['auto_sync_frequency'], - def_num=89, + 24: Field( + name='event_group', + type=BASE_TYPES[0x02], # uint8 + def_num=24, ), - 90: Field( # Allows setting specific activities auto-activity detect enabled/disabled settings - name='auto_activity_detect', - type=FIELD_TYPES['auto_activity_detect'], - def_num=90, + 25: Field( # North east corner latitude. + name='nec_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=25, + units='semicircles', ), - 94: Field( # Number of screens configured to display - name='number_of_screens', - type=BASE_TYPES[0x02], # uint8 - def_num=94, + 26: Field( # North east corner longitude. + name='nec_long', + type=BASE_TYPES[0x85], # sint32 + def_num=26, + units='semicircles', ), - 95: Field( # Smart Notification display orientation - name='smart_notification_display_orientation', - type=FIELD_TYPES['display_orientation'], - def_num=95, + 27: Field( # South west corner latitude. + name='swc_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=27, + units='semicircles', ), - 134: Field( - name='tap_interface', - type=FIELD_TYPES['switch'], - def_num=134, + 28: Field( # South west corner latitude. + name='swc_long', + type=BASE_TYPES[0x85], # sint32 + def_num=28, + units='semicircles', ), - }, - ), - 3: MessageType( - name='user_profile', - mesg_num=3, - fields={ - 0: Field( - name='friendly_name', + 29: Field( + name='name', type=BASE_TYPES[0x07], # string - def_num=0, + def_num=29, ), - 1: Field( - name='gender', - type=FIELD_TYPES['gender'], - def_num=1, + 30: Field( + name='normalized_power', + type=BASE_TYPES[0x84], # uint16 + def_num=30, + units='watts', ), - 2: Field( - name='age', - type=BASE_TYPES[0x02], # uint8 - def_num=2, - units='years', + 31: Field( + name='left_right_balance', + type=FIELD_TYPES['left_right_balance_100'], + def_num=31, ), - 3: Field( - name='height', - type=BASE_TYPES[0x02], # uint8 - def_num=3, - scale=100, - units='m', + 32: Field( + name='sub_sport', + type=FIELD_TYPES['sub_sport'], + def_num=32, ), - 4: Field( - name='weight', + 33: Field( + name='total_work', + type=BASE_TYPES[0x86], # uint32 + def_num=33, + units='J', + ), + 34: Field( + name='avg_altitude', type=BASE_TYPES[0x84], # uint16 - def_num=4, - scale=10, - units='kg', + def_num=34, + scale=5, + offset=500, + units='m', + components=( + ComponentField( + name='enhanced_avg_altitude', + def_num=91, + scale=5, + offset=500, + units='m', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), ), - 5: Field( - name='language', - type=FIELD_TYPES['language'], + 35: Field( + name='max_altitude', + type=BASE_TYPES[0x84], # uint16 + def_num=35, + scale=5, + offset=500, + units='m', + components=( + ComponentField( + name='enhanced_max_altitude', + def_num=92, + scale=5, + offset=500, + units='m', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), + ), + 36: Field( + name='gps_accuracy', + type=BASE_TYPES[0x02], # uint8 + def_num=36, + units='m', + ), + 37: Field( + name='avg_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=37, + scale=100, + units='%', + ), + 38: Field( + name='avg_pos_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=38, + scale=100, + units='%', + ), + 39: Field( + name='avg_neg_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=39, + scale=100, + units='%', + ), + 40: Field( + name='max_pos_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=40, + scale=100, + units='%', + ), + 41: Field( + name='max_neg_grade', + type=BASE_TYPES[0x83], # sint16 + def_num=41, + scale=100, + units='%', + ), + 42: Field( + name='avg_temperature', + type=BASE_TYPES[0x01], # sint8 + def_num=42, + units='C', + ), + 43: Field( + name='max_temperature', + type=BASE_TYPES[0x01], # sint8 + def_num=43, + units='C', + ), + 44: Field( + name='total_moving_time', + type=BASE_TYPES[0x86], # uint32 + def_num=44, + scale=1000, + units='s', + ), + 45: Field( + name='avg_pos_vertical_speed', + type=BASE_TYPES[0x83], # sint16 + def_num=45, + scale=1000, + units='m/s', + ), + 46: Field( + name='avg_neg_vertical_speed', + type=BASE_TYPES[0x83], # sint16 + def_num=46, + scale=1000, + units='m/s', + ), + 47: Field( + name='max_pos_vertical_speed', + type=BASE_TYPES[0x83], # sint16 + def_num=47, + scale=1000, + units='m/s', + ), + 48: Field( + name='max_neg_vertical_speed', + type=BASE_TYPES[0x83], # sint16 + def_num=48, + scale=1000, + units='m/s', + ), + 49: Field( + name='time_in_hr_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=49, + scale=1000, + units='s', + ), + 50: Field( + name='time_in_speed_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=50, + scale=1000, + units='s', + ), + 51: Field( + name='time_in_cadence_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=51, + scale=1000, + units='s', + ), + 52: Field( + name='time_in_power_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=52, + scale=1000, + units='s', + ), + 53: Field( + name='repetition_num', + type=BASE_TYPES[0x84], # uint16 + def_num=53, + ), + 54: Field( + name='min_altitude', + type=BASE_TYPES[0x84], # uint16 + def_num=54, + scale=5, + offset=500, + units='m', + components=( + ComponentField( + name='enhanced_min_altitude', + def_num=93, + scale=5, + offset=500, + units='m', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), + ), + 55: Field( + name='min_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=55, + units='bpm', + ), + 56: Field( + name='active_time', + type=BASE_TYPES[0x86], # uint32 + def_num=56, + scale=1000, + units='s', + ), + 57: Field( + name='wkt_step_index', + type=FIELD_TYPES['message_index'], + def_num=57, + ), + 58: Field( + name='sport_event', + type=FIELD_TYPES['sport_event'], + def_num=58, + ), + 59: Field( + name='avg_left_torque_effectiveness', + type=BASE_TYPES[0x02], # uint8 + def_num=59, + scale=2, + units='percent', + ), + 60: Field( + name='avg_right_torque_effectiveness', + type=BASE_TYPES[0x02], # uint8 + def_num=60, + scale=2, + units='percent', + ), + 61: Field( + name='avg_left_pedal_smoothness', + type=BASE_TYPES[0x02], # uint8 + def_num=61, + scale=2, + units='percent', + ), + 62: Field( + name='avg_right_pedal_smoothness', + type=BASE_TYPES[0x02], # uint8 + def_num=62, + scale=2, + units='percent', + ), + 63: Field( + name='avg_combined_pedal_smoothness', + type=BASE_TYPES[0x02], # uint8 + def_num=63, + scale=2, + units='percent', + ), + 64: Field( + name='status', + type=FIELD_TYPES['segment_lap_status'], + def_num=64, + ), + 65: Field( + name='uuid', + type=BASE_TYPES[0x07], # string + def_num=65, + ), + 66: Field( # fractional part of the avg_cadence + name='avg_fractional_cadence', + type=BASE_TYPES[0x02], # uint8 + def_num=66, + scale=128, + units='rpm', + ), + 67: Field( # fractional part of the max_cadence + name='max_fractional_cadence', + type=BASE_TYPES[0x02], # uint8 + def_num=67, + scale=128, + units='rpm', + ), + 68: Field( # fractional part of the total_cycles + name='total_fractional_cycles', + type=BASE_TYPES[0x02], # uint8 + def_num=68, + scale=128, + units='cycles', + ), + 69: Field( + name='front_gear_shift_count', + type=BASE_TYPES[0x84], # uint16 + def_num=69, + ), + 70: Field( + name='rear_gear_shift_count', + type=BASE_TYPES[0x84], # uint16 + def_num=70, + ), + 71: Field( # Total time spent in the standing position + name='time_standing', + type=BASE_TYPES[0x86], # uint32 + def_num=71, + scale=1000, + units='s', + ), + 72: Field( # Number of transitions to the standing state + name='stand_count', + type=BASE_TYPES[0x84], # uint16 + def_num=72, + ), + 73: Field( # Average left platform center offset + name='avg_left_pco', + type=BASE_TYPES[0x01], # sint8 + def_num=73, + units='mm', + ), + 74: Field( # Average right platform center offset + name='avg_right_pco', + type=BASE_TYPES[0x01], # sint8 + def_num=74, + units='mm', + ), + 75: Field( # Average left power phase angles. Data value indexes defined by power_phase_type. + name='avg_left_power_phase', + type=BASE_TYPES[0x02], # uint8 + def_num=75, + scale=0.7111111, + units='degrees', + ), + 76: Field( # Average left power phase peak angles. Data value indexes defined by power_phase_type. + name='avg_left_power_phase_peak', + type=BASE_TYPES[0x02], # uint8 + def_num=76, + scale=0.7111111, + units='degrees', + ), + 77: Field( # Average right power phase angles. Data value indexes defined by power_phase_type. + name='avg_right_power_phase', + type=BASE_TYPES[0x02], # uint8 + def_num=77, + scale=0.7111111, + units='degrees', + ), + 78: Field( # Average right power phase peak angles. Data value indexes defined by power_phase_type. + name='avg_right_power_phase_peak', + type=BASE_TYPES[0x02], # uint8 + def_num=78, + scale=0.7111111, + units='degrees', + ), + 79: Field( # Average power by position. Data value indexes defined by rider_position_type. + name='avg_power_position', + type=BASE_TYPES[0x84], # uint16 + def_num=79, + units='watts', + ), + 80: Field( # Maximum power by position. Data value indexes defined by rider_position_type. + name='max_power_position', + type=BASE_TYPES[0x84], # uint16 + def_num=80, + units='watts', + ), + 81: Field( # Average cadence by position. Data value indexes defined by rider_position_type. + name='avg_cadence_position', + type=BASE_TYPES[0x02], # uint8 + def_num=81, + units='rpm', + ), + 82: Field( # Maximum cadence by position. Data value indexes defined by rider_position_type. + name='max_cadence_position', + type=BASE_TYPES[0x02], # uint8 + def_num=82, + units='rpm', + ), + 83: Field( # Manufacturer that produced the segment + name='manufacturer', + type=FIELD_TYPES['manufacturer'], + def_num=83, + ), + 84: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='total_grit', + type=BASE_TYPES[0x88], # float32 + def_num=84, + units='kGrit', + ), + 85: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='total_flow', + type=BASE_TYPES[0x88], # float32 + def_num=85, + units='Flow', + ), + 86: Field( # The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes. + name='avg_grit', + type=BASE_TYPES[0x88], # float32 + def_num=86, + units='kGrit', + ), + 87: Field( # The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals. + name='avg_flow', + type=BASE_TYPES[0x88], # float32 + def_num=87, + units='Flow', + ), + 89: Field( # fractional part of total_ascent + name='total_fractional_ascent', + type=BASE_TYPES[0x02], # uint8 + def_num=89, + scale=100, + units='m', + ), + 90: Field( # fractional part of total_descent + name='total_fractional_descent', + type=BASE_TYPES[0x02], # uint8 + def_num=90, + scale=100, + units='m', + ), + 91: Field( + name='enhanced_avg_altitude', + type=BASE_TYPES[0x86], # uint32 + def_num=91, + scale=5, + offset=500, + units='m', + ), + 92: Field( + name='enhanced_max_altitude', + type=BASE_TYPES[0x86], # uint32 + def_num=92, + scale=5, + offset=500, + units='m', + ), + 93: Field( + name='enhanced_min_altitude', + type=BASE_TYPES[0x86], # uint32 + def_num=93, + scale=5, + offset=500, + units='m', + ), + 253: FIELD_TYPE_TIMESTAMP, # Lap end time. + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 148: MessageType( # Unique Identification data for a segment file + name='segment_id', + mesg_num=148, + fields={ + 0: Field( # Friendly name assigned to segment + name='name', + type=BASE_TYPES[0x07], # string + def_num=0, + ), + 1: Field( # UUID of the segment + name='uuid', + type=BASE_TYPES[0x07], # string + def_num=1, + ), + 2: Field( # Sport associated with the segment + name='sport', + type=FIELD_TYPES['sport'], + def_num=2, + ), + 3: Field( # Segment enabled for evaluation + name='enabled', + type=FIELD_TYPES['bool'], + def_num=3, + ), + 4: Field( # Primary key of the user that created the segment + name='user_profile_primary_key', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + ), + 5: Field( # ID of the device that created the segment + name='device_id', + type=BASE_TYPES[0x86], # uint32 + def_num=5, + ), + 6: Field( # Index for the Leader Board entry selected as the default race participant + name='default_race_leader', + type=BASE_TYPES[0x02], # uint8 + def_num=6, + ), + 7: Field( # Indicates if any segments should be deleted + name='delete_status', + type=FIELD_TYPES['segment_delete_status'], + def_num=7, + ), + 8: Field( # Indicates how the segment was selected to be sent to the device + name='selection_type', + type=FIELD_TYPES['segment_selection_type'], + def_num=8, + ), + }, + ), + 149: MessageType( # Unique Identification data for an individual segment leader within a segment file + name='segment_leaderboard_entry', + mesg_num=149, + fields={ + 0: Field( # Friendly name assigned to leader + name='name', + type=BASE_TYPES[0x07], # string + def_num=0, + ), + 1: Field( # Leader classification + name='type', + type=FIELD_TYPES['segment_leaderboard_type'], + def_num=1, + ), + 2: Field( # Primary user ID of this leader + name='group_primary_key', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + ), + 3: Field( # ID of the activity associated with this leader time + name='activity_id', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + ), + 4: Field( # Segment Time (includes pauses) + name='segment_time', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + scale=1000, + units='s', + ), + 5: Field( # String version of the activity_id. 21 characters long, express in decimal + name='activity_id_string', + type=BASE_TYPES[0x07], # string + def_num=5, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 150: MessageType( # Navigation and race evaluation point for a segment decribing a point along the segment path and time it took each segment leader to reach that point + name='segment_point', + mesg_num=150, + fields={ + 1: Field( + name='position_lat', + type=BASE_TYPES[0x85], # sint32 + def_num=1, + units='semicircles', + ), + 2: Field( + name='position_long', + type=BASE_TYPES[0x85], # sint32 + def_num=2, + units='semicircles', + ), + 3: Field( # Accumulated distance along the segment at the described point + name='distance', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + scale=100, + units='m', + ), + 4: Field( # Accumulated altitude along the segment at the described point + name='altitude', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + scale=5, + offset=500, + units='m', + components=( + ComponentField( + name='enhanced_altitude', + def_num=6, + scale=5, + offset=500, + units='m', + accumulate=False, + bits=16, + bit_offset=0, + ), + ), + ), + 5: Field( # Accumualted time each leader board member required to reach the described point. This value is zero for all leader board members at the starting point of the segment. + name='leader_time', + type=BASE_TYPES[0x86], # uint32 + def_num=5, + scale=1000, + units='s', + ), + 6: Field( # Accumulated altitude along the segment at the described point + name='enhanced_altitude', + type=BASE_TYPES[0x86], # uint32 + def_num=6, + scale=5, + offset=500, + units='m', + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + + + # *********************** Segment List File Messages *********************** + 151: MessageType( # Summary of the unique segment and leaderboard information associated with a segment file. This message is used to compile a segment list file describing all segment files on a device. The segment list file is used when refreshing the contents of a segment file with the latest available leaderboard information. + name='segment_file', + mesg_num=151, + fields={ + 1: Field( # UUID of the segment file + name='file_uuid', + type=BASE_TYPES[0x07], # string + def_num=1, + ), + 3: Field( # Enabled state of the segment file + name='enabled', + type=FIELD_TYPES['bool'], + def_num=3, + ), + 4: Field( # Primary key of the user that created the segment file + name='user_profile_primary_key', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + ), + 7: Field( # Leader type of each leader in the segment file + name='leader_type', + type=FIELD_TYPES['segment_leaderboard_type'], + def_num=7, + ), + 8: Field( # Group primary key of each leader in the segment file + name='leader_group_primary_key', + type=BASE_TYPES[0x86], # uint32 + def_num=8, + ), + 9: Field( # Activity ID of each leader in the segment file + name='leader_activity_id', + type=BASE_TYPES[0x86], # uint32 + def_num=9, + ), + 10: Field( # String version of the activity ID of each leader in the segment file. 21 characters long for each ID, express in decimal + name='leader_activity_id_string', + type=BASE_TYPES[0x07], # string + def_num=10, + ), + 11: Field( # Index for the Leader Board entry selected as the default race participant + name='default_race_leader', + type=BASE_TYPES[0x02], # uint8 + def_num=11, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + + + # ************************* Settings File Messages ************************* + 2: MessageType( + name='device_settings', + mesg_num=2, + fields={ + 0: Field( # Index into time zone arrays. + name='active_time_zone', + type=BASE_TYPES[0x02], # uint8 + def_num=0, + ), + 1: Field( # Offset from system time. Required to convert timestamp from system time to UTC. + name='utc_offset', + type=BASE_TYPES[0x86], # uint32 + def_num=1, + ), + 2: Field( # Offset from system time. + name='time_offset', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + units='s', + ), + 4: Field( # Display mode for the time + name='time_mode', + type=FIELD_TYPES['time_mode'], + def_num=4, + ), + 5: Field( # timezone offset in 1/4 hour increments + name='time_zone_offset', + type=BASE_TYPES[0x01], # sint8 + def_num=5, + scale=4, + units='hr', + ), + 12: Field( # Mode for backlight + name='backlight_mode', + type=FIELD_TYPES['backlight_mode'], + def_num=12, + ), + 36: Field( # Enabled state of the activity tracker functionality + name='activity_tracker_enabled', + type=FIELD_TYPES['bool'], + def_num=36, + ), + 39: Field( # UTC timestamp used to set the devices clock and date + name='clock_time', + type=FIELD_TYPES['date_time'], + def_num=39, + ), + 40: Field( # Bitfield to configure enabled screens for each supported loop + name='pages_enabled', + type=BASE_TYPES[0x84], # uint16 + def_num=40, + ), + 46: Field( # Enabled state of the move alert + name='move_alert_enabled', + type=FIELD_TYPES['bool'], + def_num=46, + ), + 47: Field( # Display mode for the date + name='date_mode', + type=FIELD_TYPES['date_mode'], + def_num=47, + ), + 55: Field( + name='display_orientation', + type=FIELD_TYPES['display_orientation'], + def_num=55, + ), + 56: Field( + name='mounting_side', + type=FIELD_TYPES['side'], + def_num=56, + ), + 57: Field( # Bitfield to indicate one page as default for each supported loop + name='default_page', + type=BASE_TYPES[0x84], # uint16 + def_num=57, + ), + 58: Field( # Minimum steps before an autosync can occur + name='autosync_min_steps', + type=BASE_TYPES[0x84], # uint16 + def_num=58, + units='steps', + ), + 59: Field( # Minimum minutes before an autosync can occur + name='autosync_min_time', + type=BASE_TYPES[0x84], # uint16 + def_num=59, + units='minutes', + ), + 80: Field( # Enable auto-detect setting for the lactate threshold feature. + name='lactate_threshold_autodetect_enabled', + type=FIELD_TYPES['bool'], + def_num=80, + ), + 86: Field( # Automatically upload using BLE + name='ble_auto_upload_enabled', + type=FIELD_TYPES['bool'], + def_num=86, + ), + 89: Field( # Helps to conserve battery by changing modes + name='auto_sync_frequency', + type=FIELD_TYPES['auto_sync_frequency'], + def_num=89, + ), + 90: Field( # Allows setting specific activities auto-activity detect enabled/disabled settings + name='auto_activity_detect', + type=FIELD_TYPES['auto_activity_detect'], + def_num=90, + ), + 94: Field( # Number of screens configured to display + name='number_of_screens', + type=BASE_TYPES[0x02], # uint8 + def_num=94, + ), + 95: Field( # Smart Notification display orientation + name='smart_notification_display_orientation', + type=FIELD_TYPES['display_orientation'], + def_num=95, + ), + 134: Field( + name='tap_interface', + type=FIELD_TYPES['switch'], + def_num=134, + ), + 174: Field( # Used to hold the tap threshold setting + name='tap_sensitivity', + type=FIELD_TYPES['tap_sensitivity'], + def_num=174, + ), + }, + ), + 3: MessageType( + name='user_profile', + mesg_num=3, + fields={ + 0: Field( # Used for Morning Report greeting + name='friendly_name', + type=BASE_TYPES[0x07], # string + def_num=0, + ), + 1: Field( + name='gender', + type=FIELD_TYPES['gender'], + def_num=1, + ), + 2: Field( + name='age', + type=BASE_TYPES[0x02], # uint8 + def_num=2, + units='years', + ), + 3: Field( + name='height', + type=BASE_TYPES[0x02], # uint8 + def_num=3, + scale=100, + units='m', + ), + 4: Field( + name='weight', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + scale=10, + units='kg', + ), + 5: Field( + name='language', + type=FIELD_TYPES['language'], + def_num=5, + ), + 6: Field( + name='elev_setting', + type=FIELD_TYPES['display_measure'], + def_num=6, + ), + 7: Field( + name='weight_setting', + type=FIELD_TYPES['display_measure'], + def_num=7, + ), + 8: Field( + name='resting_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=8, + units='bpm', + ), + 9: Field( + name='default_max_running_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=9, + units='bpm', + ), + 10: Field( + name='default_max_biking_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=10, + units='bpm', + ), + 11: Field( + name='default_max_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=11, + units='bpm', + ), + 12: Field( + name='hr_setting', + type=FIELD_TYPES['display_heart'], + def_num=12, + ), + 13: Field( + name='speed_setting', + type=FIELD_TYPES['display_measure'], + def_num=13, + ), + 14: Field( + name='dist_setting', + type=FIELD_TYPES['display_measure'], + def_num=14, + ), + 16: Field( + name='power_setting', + type=FIELD_TYPES['display_power'], + def_num=16, + ), + 17: Field( + name='activity_class', + type=FIELD_TYPES['activity_class'], + def_num=17, + ), + 18: Field( + name='position_setting', + type=FIELD_TYPES['display_position'], + def_num=18, + ), + 21: Field( + name='temperature_setting', + type=FIELD_TYPES['display_measure'], + def_num=21, + ), + 22: Field( + name='local_id', + type=FIELD_TYPES['user_local_id'], + def_num=22, + ), + 23: Field( + name='global_id', + type=BASE_TYPES[0x0D], # byte + def_num=23, + ), + 28: Field( # Typical wake time + name='wake_time', + type=FIELD_TYPES['localtime_into_day'], + def_num=28, + ), + 29: Field( # Typical bed time + name='sleep_time', + type=FIELD_TYPES['localtime_into_day'], + def_num=29, + ), + 30: Field( + name='height_setting', + type=FIELD_TYPES['display_measure'], + def_num=30, + ), + 31: Field( # User defined running step length set to 0 for auto length + name='user_running_step_length', + type=BASE_TYPES[0x84], # uint16 + def_num=31, + scale=1000, + units='m', + ), + 32: Field( # User defined walking step length set to 0 for auto length + name='user_walking_step_length', + type=BASE_TYPES[0x84], # uint16 + def_num=32, + scale=1000, + units='m', + ), + 47: Field( + name='depth_setting', + type=FIELD_TYPES['display_measure'], + def_num=47, + ), + 49: Field( + name='dive_count', + type=BASE_TYPES[0x86], # uint32 + def_num=49, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 4: MessageType( + name='hrm_profile', + mesg_num=4, + fields={ + 0: Field( + name='enabled', + type=FIELD_TYPES['bool'], + def_num=0, + ), + 1: Field( + name='hrm_ant_id', + type=BASE_TYPES[0x8B], # uint16z + def_num=1, + ), + 2: Field( + name='log_hrv', + type=FIELD_TYPES['bool'], + def_num=2, + ), + 3: Field( + name='hrm_ant_id_trans_type', + type=BASE_TYPES[0x0A], # uint8z + def_num=3, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 5: MessageType( + name='sdm_profile', + mesg_num=5, + fields={ + 0: Field( + name='enabled', + type=FIELD_TYPES['bool'], + def_num=0, + ), + 1: Field( + name='sdm_ant_id', + type=BASE_TYPES[0x8B], # uint16z + def_num=1, + ), + 2: Field( + name='sdm_cal_factor', + type=BASE_TYPES[0x84], # uint16 + def_num=2, + scale=10, + units='%', + ), + 3: Field( + name='odometer', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + scale=100, + units='m', + ), + 4: Field( # Use footpod for speed source instead of GPS + name='speed_source', + type=FIELD_TYPES['bool'], + def_num=4, + ), + 5: Field( + name='sdm_ant_id_trans_type', + type=BASE_TYPES[0x0A], # uint8z + def_num=5, + ), + 7: Field( # Rollover counter that can be used to extend the odometer + name='odometer_rollover', + type=BASE_TYPES[0x02], # uint8 + def_num=7, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 6: MessageType( + name='bike_profile', + mesg_num=6, + fields={ + 0: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=0, + ), + 1: Field( + name='sport', + type=FIELD_TYPES['sport'], + def_num=1, + ), + 2: Field( + name='sub_sport', + type=FIELD_TYPES['sub_sport'], + def_num=2, + ), + 3: Field( + name='odometer', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + scale=100, + units='m', + ), + 4: Field( + name='bike_spd_ant_id', + type=BASE_TYPES[0x8B], # uint16z + def_num=4, + ), + 5: Field( + name='bike_cad_ant_id', + type=BASE_TYPES[0x8B], # uint16z + def_num=5, + ), + 6: Field( + name='bike_spdcad_ant_id', + type=BASE_TYPES[0x8B], # uint16z + def_num=6, + ), + 7: Field( + name='bike_power_ant_id', + type=BASE_TYPES[0x8B], # uint16z + def_num=7, + ), + 8: Field( + name='custom_wheelsize', + type=BASE_TYPES[0x84], # uint16 + def_num=8, + scale=1000, + units='m', + ), + 9: Field( + name='auto_wheelsize', + type=BASE_TYPES[0x84], # uint16 + def_num=9, + scale=1000, + units='m', + ), + 10: Field( + name='bike_weight', + type=BASE_TYPES[0x84], # uint16 + def_num=10, + scale=10, + units='kg', + ), + 11: Field( + name='power_cal_factor', + type=BASE_TYPES[0x84], # uint16 + def_num=11, + scale=10, + units='%', + ), + 12: Field( + name='auto_wheel_cal', + type=FIELD_TYPES['bool'], + def_num=12, + ), + 13: Field( + name='auto_power_zero', + type=FIELD_TYPES['bool'], + def_num=13, + ), + 14: Field( + name='id', + type=BASE_TYPES[0x02], # uint8 + def_num=14, + ), + 15: Field( + name='spd_enabled', + type=FIELD_TYPES['bool'], + def_num=15, + ), + 16: Field( + name='cad_enabled', + type=FIELD_TYPES['bool'], + def_num=16, + ), + 17: Field( + name='spdcad_enabled', + type=FIELD_TYPES['bool'], + def_num=17, + ), + 18: Field( + name='power_enabled', + type=FIELD_TYPES['bool'], + def_num=18, + ), + 19: Field( + name='crank_length', + type=BASE_TYPES[0x02], # uint8 + def_num=19, + scale=2, + offset=-110, + units='mm', + ), + 20: Field( + name='enabled', + type=FIELD_TYPES['bool'], + def_num=20, + ), + 21: Field( + name='bike_spd_ant_id_trans_type', + type=BASE_TYPES[0x0A], # uint8z + def_num=21, + ), + 22: Field( + name='bike_cad_ant_id_trans_type', + type=BASE_TYPES[0x0A], # uint8z + def_num=22, + ), + 23: Field( + name='bike_spdcad_ant_id_trans_type', + type=BASE_TYPES[0x0A], # uint8z + def_num=23, + ), + 24: Field( + name='bike_power_ant_id_trans_type', + type=BASE_TYPES[0x0A], # uint8z + def_num=24, + ), + 37: Field( # Rollover counter that can be used to extend the odometer + name='odometer_rollover', + type=BASE_TYPES[0x02], # uint8 + def_num=37, + ), + 38: Field( # Number of front gears + name='front_gear_num', + type=BASE_TYPES[0x0A], # uint8z + def_num=38, + ), + 39: Field( # Number of teeth on each gear 0 is innermost + name='front_gear', + type=BASE_TYPES[0x0A], # uint8z + def_num=39, + ), + 40: Field( # Number of rear gears + name='rear_gear_num', + type=BASE_TYPES[0x0A], # uint8z + def_num=40, + ), + 41: Field( # Number of teeth on each gear 0 is innermost + name='rear_gear', + type=BASE_TYPES[0x0A], # uint8z + def_num=41, + ), + 44: Field( + name='shimano_di2_enabled', + type=FIELD_TYPES['bool'], + def_num=44, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 127: MessageType( + name='connectivity', + mesg_num=127, + fields={ + 0: Field( # Use Bluetooth for connectivity features + name='bluetooth_enabled', + type=FIELD_TYPES['bool'], + def_num=0, + ), + 1: Field( # Use Bluetooth Low Energy for connectivity features + name='bluetooth_le_enabled', + type=FIELD_TYPES['bool'], + def_num=1, + ), + 2: Field( # Use ANT for connectivity features + name='ant_enabled', + type=FIELD_TYPES['bool'], + def_num=2, + ), + 3: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=3, + ), + 4: Field( + name='live_tracking_enabled', + type=FIELD_TYPES['bool'], + def_num=4, + ), + 5: Field( + name='weather_conditions_enabled', + type=FIELD_TYPES['bool'], + def_num=5, + ), + 6: Field( + name='weather_alerts_enabled', + type=FIELD_TYPES['bool'], + def_num=6, + ), + 7: Field( + name='auto_activity_upload_enabled', + type=FIELD_TYPES['bool'], + def_num=7, + ), + 8: Field( + name='course_download_enabled', + type=FIELD_TYPES['bool'], + def_num=8, + ), + 9: Field( + name='workout_download_enabled', + type=FIELD_TYPES['bool'], + def_num=9, + ), + 10: Field( + name='gps_ephemeris_download_enabled', + type=FIELD_TYPES['bool'], + def_num=10, + ), + 11: Field( + name='incident_detection_enabled', + type=FIELD_TYPES['bool'], + def_num=11, + ), + 12: Field( + name='grouptrack_enabled', + type=FIELD_TYPES['bool'], + def_num=12, + ), + }, + ), + 159: MessageType( + name='watchface_settings', + mesg_num=159, + fields={ + 0: Field( + name='mode', + type=FIELD_TYPES['watchface_mode'], + def_num=0, + ), + 1: Field( + name='layout', + type=BASE_TYPES[0x0D], # byte + def_num=1, + subfields=( + SubField( + name='analog_layout', + def_num=1, + type=FIELD_TYPES['analog_watchface_layout'], + ref_fields=( + ReferenceField( + name='mode', + def_num=0, + value='analog', + raw_value=1, + ), + ), + ), + SubField( + name='digital_layout', + def_num=1, + type=FIELD_TYPES['digital_watchface_layout'], + ref_fields=( + ReferenceField( + name='mode', + def_num=0, + value='digital', + raw_value=0, + ), + ), + ), + ), + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 188: MessageType( + name='ohr_settings', + mesg_num=188, + fields={ + 0: Field( + name='enabled', + type=FIELD_TYPES['switch'], + def_num=0, + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + 216: MessageType( + name='time_in_zone', + mesg_num=216, + fields={ + 0: Field( + name='reference_mesg', + type=FIELD_TYPES['mesg_num'], + def_num=0, + ), + 1: Field( + name='reference_index', + type=FIELD_TYPES['message_index'], + def_num=1, + ), + 2: Field( + name='time_in_hr_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + scale=1000, + units='s', + ), + 3: Field( + name='time_in_speed_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=3, + scale=1000, + units='s', + ), + 4: Field( + name='time_in_cadence_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + scale=1000, + units='s', + ), + 5: Field( + name='time_in_power_zone', + type=BASE_TYPES[0x86], # uint32 + def_num=5, + scale=1000, + units='s', + ), + 6: Field( + name='hr_zone_high_boundary', + type=BASE_TYPES[0x02], # uint8 + def_num=6, + units='bpm', + ), + 7: Field( + name='speed_zone_high_boundary', + type=BASE_TYPES[0x84], # uint16 + def_num=7, + scale=1000, + units='m/s', + ), + 8: Field( + name='cadence_zone_high_bondary', + type=BASE_TYPES[0x02], # uint8 + def_num=8, + units='rpm', + ), + 9: Field( + name='power_zone_high_boundary', + type=BASE_TYPES[0x84], # uint16 + def_num=9, + units='watts', + ), + 10: Field( + name='hr_calc_type', + type=FIELD_TYPES['hr_zone_calc'], + def_num=10, + ), + 11: Field( + name='max_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=11, + ), + 12: Field( + name='resting_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=12, + ), + 13: Field( + name='threshold_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=13, + ), + 14: Field( + name='pwr_calc_type', + type=FIELD_TYPES['pwr_zone_calc'], + def_num=14, + ), + 15: Field( + name='functional_threshold_power', + type=BASE_TYPES[0x84], # uint16 + def_num=15, + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + + + # ********************** Sport Settings File Messages ********************** + 7: MessageType( + name='zones_target', + mesg_num=7, + fields={ + 1: Field( + name='max_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=1, + ), + 2: Field( + name='threshold_heart_rate', + type=BASE_TYPES[0x02], # uint8 + def_num=2, + ), + 3: Field( + name='functional_threshold_power', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + ), + 5: Field( + name='hr_calc_type', + type=FIELD_TYPES['hr_zone_calc'], + def_num=5, + ), + 7: Field( + name='pwr_calc_type', + type=FIELD_TYPES['pwr_zone_calc'], + def_num=7, + ), + }, + ), + 8: MessageType( + name='hr_zone', + mesg_num=8, + fields={ + 1: Field( + name='high_bpm', + type=BASE_TYPES[0x02], # uint8 + def_num=1, + units='bpm', + ), + 2: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=2, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 9: MessageType( + name='power_zone', + mesg_num=9, + fields={ + 1: Field( + name='high_value', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + units='watts', + ), + 2: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=2, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 10: MessageType( + name='met_zone', + mesg_num=10, + fields={ + 1: Field( + name='high_bpm', + type=BASE_TYPES[0x02], # uint8 + def_num=1, + ), + 2: Field( + name='calories', + type=BASE_TYPES[0x84], # uint16 + def_num=2, + scale=10, + units='kcal/min', + ), + 3: Field( + name='fat_calories', + type=BASE_TYPES[0x02], # uint8 + def_num=3, + scale=10, + units='kcal/min', + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 12: MessageType( + name='sport', + mesg_num=12, + fields={ + 0: Field( + name='sport', + type=FIELD_TYPES['sport'], + def_num=0, + ), + 1: Field( + name='sub_sport', + type=FIELD_TYPES['sub_sport'], + def_num=1, + ), + 3: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=3, + ), + }, + ), + 13: MessageType( + name='training_settings', + mesg_num=13, + fields={ + 31: Field( + name='target_distance', + type=BASE_TYPES[0x86], # uint32 + def_num=31, + scale=100, + units='m', + ), + 32: Field( + name='target_speed', + type=BASE_TYPES[0x84], # uint16 + def_num=32, + scale=1000, + units='m/s', + ), + 33: Field( + name='target_time', + type=BASE_TYPES[0x86], # uint32 + def_num=33, + units='s', + ), + 153: Field( # A more precise target speed field + name='precise_target_speed', + type=BASE_TYPES[0x86], # uint32 + def_num=153, + scale=1000000, + units='m/s', + ), + }, + ), + 53: MessageType( + name='speed_zone', + mesg_num=53, + fields={ + 0: Field( + name='high_value', + type=BASE_TYPES[0x84], # uint16 + def_num=0, + scale=1000, + units='m/s', + ), + 1: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=1, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 131: MessageType( + name='cadence_zone', + mesg_num=131, + fields={ + 0: Field( + name='high_value', + type=BASE_TYPES[0x02], # uint8 + def_num=0, + units='rpm', + ), + 1: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=1, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 258: MessageType( + name='dive_settings', + mesg_num=258, + fields={ + 0: Field( + name='name', + type=BASE_TYPES[0x07], # string + def_num=0, + ), + 1: Field( + name='model', + type=FIELD_TYPES['tissue_model_type'], + def_num=1, + ), + 2: Field( + name='gf_low', + type=BASE_TYPES[0x02], # uint8 + def_num=2, + units='percent', + ), + 3: Field( + name='gf_high', + type=BASE_TYPES[0x02], # uint8 + def_num=3, + units='percent', + ), + 4: Field( + name='water_type', + type=FIELD_TYPES['water_type'], + def_num=4, + ), + 5: Field( # Fresh water is usually 1000; salt water is usually 1025 + name='water_density', + type=BASE_TYPES[0x88], # float32 + def_num=5, + units='kg/m^3', + ), + 6: Field( # Typically 1.40 + name='po2_warn', + type=BASE_TYPES[0x02], # uint8 + def_num=6, + scale=100, + units='percent', + ), + 7: Field( # Typically 1.60 + name='po2_critical', + type=BASE_TYPES[0x02], # uint8 + def_num=7, + scale=100, + units='percent', + ), + 8: Field( + name='po2_deco', + type=BASE_TYPES[0x02], # uint8 + def_num=8, + scale=100, + units='percent', + ), + 9: Field( + name='safety_stop_enabled', + type=FIELD_TYPES['bool'], + def_num=9, + ), + 10: Field( + name='bottom_depth', + type=BASE_TYPES[0x88], # float32 + def_num=10, + ), + 11: Field( + name='bottom_time', + type=BASE_TYPES[0x86], # uint32 + def_num=11, + ), + 12: Field( + name='apnea_countdown_enabled', + type=FIELD_TYPES['bool'], + def_num=12, + ), + 13: Field( + name='apnea_countdown_time', + type=BASE_TYPES[0x86], # uint32 + def_num=13, + ), + 14: Field( + name='backlight_mode', + type=FIELD_TYPES['dive_backlight_mode'], + def_num=14, + ), + 15: Field( + name='backlight_brightness', + type=BASE_TYPES[0x02], # uint8 + def_num=15, + ), + 16: Field( + name='backlight_timeout', + type=FIELD_TYPES['backlight_timeout'], + def_num=16, + ), + 17: Field( # Time between surfacing and ending the activity + name='repeat_dive_interval', + type=BASE_TYPES[0x84], # uint16 + def_num=17, + units='s', + ), + 18: Field( # Time at safety stop (if enabled) + name='safety_stop_time', + type=BASE_TYPES[0x84], # uint16 + def_num=18, + units='s', + ), + 19: Field( + name='heart_rate_source_type', + type=FIELD_TYPES['source_type'], + def_num=19, + ), + 20: Field( + name='heart_rate_source', + type=BASE_TYPES[0x02], # uint8 + def_num=20, + subfields=( + SubField( + name='heart_rate_antplus_device_type', + def_num=20, + type=FIELD_TYPES['antplus_device_type'], + ref_fields=( + ReferenceField( + name='heart_rate_source_type', + def_num=19, + value='antplus', + raw_value=1, + ), + ), + ), + SubField( + name='heart_rate_local_device_type', + def_num=20, + type=FIELD_TYPES['local_device_type'], + ref_fields=( + ReferenceField( + name='heart_rate_source_type', + def_num=19, + value='local', + raw_value=5, + ), + ), + ), + ), + ), + 21: Field( # Index of travel dive_gas message + name='travel_gas', + type=FIELD_TYPES['message_index'], + def_num=21, + ), + 22: Field( # If low PO2 should be switched to automatically + name='ccr_low_setpoint_switch_mode', + type=FIELD_TYPES['ccr_setpoint_switch_mode'], + def_num=22, + ), + 23: Field( # Target PO2 when using low setpoint + name='ccr_low_setpoint', + type=BASE_TYPES[0x02], # uint8 + def_num=23, + scale=100, + units='percent', + ), + 24: Field( # Depth to switch to low setpoint in automatic mode + name='ccr_low_setpoint_depth', + type=BASE_TYPES[0x86], # uint32 + def_num=24, + scale=1000, + units='m', + ), + 25: Field( # If high PO2 should be switched to automatically + name='ccr_high_setpoint_switch_mode', + type=FIELD_TYPES['ccr_setpoint_switch_mode'], + def_num=25, + ), + 26: Field( # Target PO2 when using high setpoint + name='ccr_high_setpoint', + type=BASE_TYPES[0x02], # uint8 + def_num=26, + scale=100, + units='percent', + ), + 27: Field( # Depth to switch to high setpoint in automatic mode + name='ccr_high_setpoint_depth', + type=BASE_TYPES[0x86], # uint32 + def_num=27, + scale=1000, + units='m', + ), + 29: Field( # Type of gas consumption rate to display. Some values are only valid if tank volume is known. + name='gas_consumption_display', + type=FIELD_TYPES['gas_consumption_rate_type'], + def_num=29, + ), + 30: Field( # Indicates whether the up key is enabled during dives + name='up_key_enabled', + type=FIELD_TYPES['bool'], + def_num=30, + ), + 35: Field( # Sounds and vibration enabled or disabled in-dive + name='dive_sounds', + type=FIELD_TYPES['tone'], + def_num=35, + ), + 36: Field( # Usually 1.0/1.5/2.0 representing 3/4.5/6m or 10/15/20ft + name='last_stop_multiple', + type=BASE_TYPES[0x02], # uint8 + def_num=36, + scale=10, + ), + 37: Field( # Indicates which guidelines to use for no-fly surface interval. + name='no_fly_time_mode', + type=FIELD_TYPES['no_fly_time_mode'], + def_num=37, + ), + 253: FIELD_TYPE_TIMESTAMP, + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 259: MessageType( + name='dive_gas', + mesg_num=259, + fields={ + 0: Field( + name='helium_content', + type=BASE_TYPES[0x02], # uint8 + def_num=0, + units='percent', + ), + 1: Field( + name='oxygen_content', + type=BASE_TYPES[0x02], # uint8 + def_num=1, + units='percent', + ), + 2: Field( + name='status', + type=FIELD_TYPES['dive_gas_status'], + def_num=2, + ), + 3: Field( + name='mode', + type=FIELD_TYPES['dive_gas_mode'], + def_num=3, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 262: MessageType( + name='dive_alarm', + mesg_num=262, + fields={ + 0: Field( # Depth setting (m) for depth type alarms + name='depth', + type=BASE_TYPES[0x86], # uint32 + def_num=0, + scale=1000, + units='m', + ), + 1: Field( # Time setting (s) for time type alarms + name='time', + type=BASE_TYPES[0x85], # sint32 + def_num=1, + units='s', + ), + 2: Field( # Enablement flag + name='enabled', + type=FIELD_TYPES['bool'], + def_num=2, + ), + 3: Field( # Alarm type setting + name='alarm_type', + type=FIELD_TYPES['dive_alarm_type'], + def_num=3, + ), + 4: Field( # Tone and Vibe setting for the alarm + name='sound', + type=FIELD_TYPES['tone'], + def_num=4, + ), + 5: Field( # Dive types the alarm will trigger on + name='dive_types', + type=FIELD_TYPES['sub_sport'], + def_num=5, + ), + 6: Field( # Alarm ID + name='id', + type=BASE_TYPES[0x86], # uint32 + def_num=6, + ), + 7: Field( # Show a visible pop-up for this alarm + name='popup_enabled', + type=FIELD_TYPES['bool'], + def_num=7, + ), + 8: Field( # Trigger the alarm on descent + name='trigger_on_descent', + type=FIELD_TYPES['bool'], + def_num=8, + ), + 9: Field( # Trigger the alarm on ascent + name='trigger_on_ascent', + type=FIELD_TYPES['bool'], + def_num=9, + ), + 10: Field( # Repeat alarm each time threshold is crossed? + name='repeating', + type=FIELD_TYPES['bool'], + def_num=10, + ), + 11: Field( # Ascent/descent rate (mps) setting for speed type alarms + name='speed', + type=BASE_TYPES[0x85], # sint32 + def_num=11, + scale=1000, + units='mps', + ), + 254: Field( # Index of the alarm + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 393: MessageType( + name='dive_apnea_alarm', + mesg_num=393, + fields={ + 0: Field( # Depth setting (m) for depth type alarms + name='depth', + type=BASE_TYPES[0x86], # uint32 + def_num=0, + scale=1000, + units='m', + ), + 1: Field( # Time setting (s) for time type alarms + name='time', + type=BASE_TYPES[0x85], # sint32 + def_num=1, + units='s', + ), + 2: Field( # Enablement flag + name='enabled', + type=FIELD_TYPES['bool'], + def_num=2, + ), + 3: Field( # Alarm type setting + name='alarm_type', + type=FIELD_TYPES['dive_alarm_type'], + def_num=3, + ), + 4: Field( # Tone and Vibe setting for the alarm. + name='sound', + type=FIELD_TYPES['tone'], + def_num=4, + ), + 5: Field( # Dive types the alarm will trigger on + name='dive_types', + type=FIELD_TYPES['sub_sport'], + def_num=5, + ), + 6: Field( # Alarm ID + name='id', + type=BASE_TYPES[0x86], # uint32 + def_num=6, + ), + 7: Field( # Show a visible pop-up for this alarm + name='popup_enabled', + type=FIELD_TYPES['bool'], + def_num=7, + ), + 8: Field( # Trigger the alarm on descent + name='trigger_on_descent', + type=FIELD_TYPES['bool'], + def_num=8, + ), + 9: Field( # Trigger the alarm on ascent + name='trigger_on_ascent', + type=FIELD_TYPES['bool'], + def_num=9, + ), + 10: Field( # Repeat alarm each time threshold is crossed? + name='repeating', + type=FIELD_TYPES['bool'], + def_num=10, + ), + 11: Field( # Ascent/descent rate (mps) setting for speed type alarms + name='speed', + type=BASE_TYPES[0x85], # sint32 + def_num=11, + scale=1000, + units='mps', + ), + 254: Field( # Index of the alarm + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + + + # ************************** Totals File Messages ************************** + 33: MessageType( + name='totals', + mesg_num=33, + fields={ + 0: Field( # Excludes pauses + name='timer_time', + type=BASE_TYPES[0x86], # uint32 + def_num=0, + units='s', + ), + 1: Field( + name='distance', + type=BASE_TYPES[0x86], # uint32 + def_num=1, + units='m', + ), + 2: Field( + name='calories', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + units='kcal', + ), + 3: Field( + name='sport', + type=FIELD_TYPES['sport'], + def_num=3, + ), + 4: Field( # Includes pauses + name='elapsed_time', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + units='s', + ), + 5: Field( + name='sessions', + type=BASE_TYPES[0x84], # uint16 + def_num=5, + ), + 6: Field( + name='active_time', + type=BASE_TYPES[0x86], # uint32 + def_num=6, + units='s', + ), + 9: Field( + name='sport_index', + type=BASE_TYPES[0x02], # uint8 + def_num=9, + ), + 253: FIELD_TYPE_TIMESTAMP, + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + + + # *********************** Weight Scale File Messages *********************** + 30: MessageType( + name='weight_scale', + mesg_num=30, + fields={ + 0: Field( + name='weight', + type=FIELD_TYPES['weight'], + def_num=0, + scale=100, + units='kg', + ), + 1: Field( + name='percent_fat', + type=BASE_TYPES[0x84], # uint16 + def_num=1, + scale=100, + units='%', + ), + 2: Field( + name='percent_hydration', + type=BASE_TYPES[0x84], # uint16 + def_num=2, + scale=100, + units='%', + ), + 3: Field( + name='visceral_fat_mass', + type=BASE_TYPES[0x84], # uint16 + def_num=3, + scale=100, + units='kg', + ), + 4: Field( + name='bone_mass', + type=BASE_TYPES[0x84], # uint16 + def_num=4, + scale=100, + units='kg', + ), + 5: Field( + name='muscle_mass', + type=BASE_TYPES[0x84], # uint16 + def_num=5, + scale=100, + units='kg', + ), + 7: Field( + name='basal_met', + type=BASE_TYPES[0x84], # uint16 + def_num=7, + scale=4, + units='kcal/day', + ), + 8: Field( + name='physique_rating', + type=BASE_TYPES[0x02], # uint8 + def_num=8, + ), + 9: Field( # ~4kJ per kcal, 0.25 allows max 16384 kcal + name='active_met', + type=BASE_TYPES[0x84], # uint16 + def_num=9, + scale=4, + units='kcal/day', + ), + 10: Field( + name='metabolic_age', + type=BASE_TYPES[0x02], # uint8 + def_num=10, + units='years', + ), + 11: Field( + name='visceral_fat_rating', + type=BASE_TYPES[0x02], # uint8 + def_num=11, + ), + 12: Field( # Associates this weight scale message to a user. This corresponds to the index of the user profile message in the weight scale file. + name='user_profile_index', + type=FIELD_TYPES['message_index'], + def_num=12, + ), + 13: Field( + name='bmi', + type=BASE_TYPES[0x84], # uint16 + def_num=13, + scale=10, + units='kg/m^2', + ), + 253: FIELD_TYPE_TIMESTAMP, + }, + ), + + + # ************************* Workout File Messages ************************** + 26: MessageType( + name='workout', + mesg_num=26, + fields={ + 4: Field( + name='sport', + type=FIELD_TYPES['sport'], + def_num=4, + ), + 5: Field( + name='capabilities', + type=FIELD_TYPES['workout_capabilities'], + def_num=5, + ), + 6: Field( # number of valid steps + name='num_valid_steps', + type=BASE_TYPES[0x84], # uint16 + def_num=6, + ), + 8: Field( + name='wkt_name', + type=BASE_TYPES[0x07], # string + def_num=8, + ), + 11: Field( + name='sub_sport', + type=FIELD_TYPES['sub_sport'], + def_num=11, + ), + 14: Field( + name='pool_length', + type=BASE_TYPES[0x84], # uint16 + def_num=14, + scale=100, + units='m', + ), + 15: Field( + name='pool_length_unit', + type=FIELD_TYPES['display_measure'], + def_num=15, + ), + 17: Field( # Description of the workout + name='wkt_description', + type=BASE_TYPES[0x07], # string + def_num=17, + ), + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, + ), + }, + ), + 27: MessageType( + name='workout_step', + mesg_num=27, + fields={ + 0: Field( + name='wkt_step_name', + type=BASE_TYPES[0x07], # string + def_num=0, + ), + 1: Field( + name='duration_type', + type=FIELD_TYPES['wkt_step_duration'], + def_num=1, + ), + 2: Field( + name='duration_value', + type=BASE_TYPES[0x86], # uint32 + def_num=2, + subfields=( + SubField( + name='duration_calories', + def_num=2, + type=BASE_TYPES[0x86], # uint32 + units='calories', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='calories', + raw_value=4, + ), + ), + ), + SubField( + name='duration_distance', + def_num=2, + type=BASE_TYPES[0x86], # uint32 + scale=100, + units='m', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='distance', + raw_value=1, + ), + ), + ), + SubField( + name='duration_hr', + def_num=2, + type=FIELD_TYPES['workout_hr'], + units='% or bpm', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='hr_less_than', + raw_value=2, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='hr_greater_than', + raw_value=3, + ), + ), + ), + SubField( + name='duration_power', + def_num=2, + type=FIELD_TYPES['workout_power'], + units='% or watts', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='power_less_than', + raw_value=14, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='power_greater_than', + raw_value=15, + ), + ), + ), + SubField( + name='duration_reps', + def_num=2, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='reps', + raw_value=29, + ), + ), + ), + SubField( # message_index of step to loop back to. Steps are assumed to be in the order by message_index. custom_name and intensity members are undefined for this duration type. + name='duration_step', + def_num=2, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_steps_cmplt', + raw_value=6, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_time', + raw_value=7, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_distance', + raw_value=8, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_calories', + raw_value=9, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_hr_less_than', + raw_value=10, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_hr_greater_than', + raw_value=11, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_power_less_than', + raw_value=12, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_power_greater_than', + raw_value=13, + ), + ), + ), + SubField( + name='duration_time', + def_num=2, + type=BASE_TYPES[0x86], # uint32 + scale=1000, + units='s', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='time', + raw_value=0, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repetition_time', + raw_value=28, + ), + ), + ), + ), + ), + 3: Field( + name='target_type', + type=FIELD_TYPES['wkt_step_target'], + def_num=3, + ), + 4: Field( + name='target_value', + type=BASE_TYPES[0x86], # uint32 + def_num=4, + subfields=( + SubField( + name='repeat_calories', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + units='calories', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_calories', + raw_value=9, + ), + ), + ), + SubField( + name='repeat_distance', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + scale=100, + units='m', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_distance', + raw_value=8, + ), + ), + ), + SubField( + name='repeat_hr', + def_num=4, + type=FIELD_TYPES['workout_hr'], + units='% or bpm', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_hr_less_than', + raw_value=10, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_hr_greater_than', + raw_value=11, + ), + ), + ), + SubField( + name='repeat_power', + def_num=4, + type=FIELD_TYPES['workout_power'], + units='% or watts', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_power_less_than', + raw_value=12, + ), + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_power_greater_than', + raw_value=13, + ), + ), + ), + SubField( # # of repetitions + name='repeat_steps', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_steps_cmplt', + raw_value=6, + ), + ), + ), + SubField( + name='repeat_time', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + scale=1000, + units='s', + ref_fields=( + ReferenceField( + name='duration_type', + def_num=1, + value='repeat_until_time', + raw_value=7, + ), + ), + ), + SubField( # Zone (1-?); Custom = 0; + name='target_cadence_zone', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='cadence', + raw_value=3, + ), + ), + ), + SubField( # hr zone (1-5);Custom =0; + name='target_hr_zone', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='heart_rate', + raw_value=1, + ), + ), + ), + SubField( # Power Zone ( 1-7); Custom = 0; + name='target_power_zone', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='power', + raw_value=4, + ), + ), + ), + SubField( # speed zone (1-10);Custom =0; + name='target_speed_zone', + def_num=4, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='speed', + raw_value=0, + ), + ), + ), + SubField( + name='target_stroke_type', + def_num=4, + type=FIELD_TYPES['swim_stroke'], + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='swim_stroke', + raw_value=11, + ), + ), + ), + ), + ), + 5: Field( + name='custom_target_value_low', + type=BASE_TYPES[0x86], # uint32 def_num=5, + subfields=( + SubField( + name='custom_target_cadence_low', + def_num=5, + type=BASE_TYPES[0x86], # uint32 + units='rpm', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='cadence', + raw_value=3, + ), + ), + ), + SubField( + name='custom_target_heart_rate_low', + def_num=5, + type=FIELD_TYPES['workout_hr'], + units='% or bpm', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='heart_rate', + raw_value=1, + ), + ), + ), + SubField( + name='custom_target_power_low', + def_num=5, + type=FIELD_TYPES['workout_power'], + units='% or watts', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='power', + raw_value=4, + ), + ), + ), + SubField( + name='custom_target_speed_low', + def_num=5, + type=BASE_TYPES[0x86], # uint32 + scale=1000, + units='m/s', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='speed', + raw_value=0, + ), + ), + ), + ), ), 6: Field( - name='elev_setting', - type=FIELD_TYPES['display_measure'], + name='custom_target_value_high', + type=BASE_TYPES[0x86], # uint32 def_num=6, + subfields=( + SubField( + name='custom_target_cadence_high', + def_num=6, + type=BASE_TYPES[0x86], # uint32 + units='rpm', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='cadence', + raw_value=3, + ), + ), + ), + SubField( + name='custom_target_heart_rate_high', + def_num=6, + type=FIELD_TYPES['workout_hr'], + units='% or bpm', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='heart_rate', + raw_value=1, + ), + ), + ), + SubField( + name='custom_target_power_high', + def_num=6, + type=FIELD_TYPES['workout_power'], + units='% or watts', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='power', + raw_value=4, + ), + ), + ), + SubField( + name='custom_target_speed_high', + def_num=6, + type=BASE_TYPES[0x86], # uint32 + scale=1000, + units='m/s', + ref_fields=( + ReferenceField( + name='target_type', + def_num=3, + value='speed', + raw_value=0, + ), + ), + ), + ), ), 7: Field( - name='weight_setting', - type=FIELD_TYPES['display_measure'], + name='intensity', + type=FIELD_TYPES['intensity'], def_num=7, ), 8: Field( - name='resting_heart_rate', - type=BASE_TYPES[0x02], # uint8 + name='notes', + type=BASE_TYPES[0x07], # string def_num=8, - units='bpm', ), 9: Field( - name='default_max_running_heart_rate', - type=BASE_TYPES[0x02], # uint8 + name='equipment', + type=FIELD_TYPES['workout_equipment'], def_num=9, - units='bpm', ), 10: Field( - name='default_max_biking_heart_rate', - type=BASE_TYPES[0x02], # uint8 + name='exercise_category', + type=FIELD_TYPES['exercise_category'], def_num=10, - units='bpm', ), 11: Field( - name='default_max_heart_rate', - type=BASE_TYPES[0x02], # uint8 + name='exercise_name', + type=BASE_TYPES[0x84], # uint16 def_num=11, - units='bpm', ), 12: Field( - name='hr_setting', - type=FIELD_TYPES['display_heart'], + name='exercise_weight', + type=BASE_TYPES[0x84], # uint16 def_num=12, + scale=100, + units='kg', ), 13: Field( - name='speed_setting', - type=FIELD_TYPES['display_measure'], + name='weight_display_unit', + type=FIELD_TYPES['fit_base_unit'], def_num=13, ), - 14: Field( - name='dist_setting', - type=FIELD_TYPES['display_measure'], - def_num=14, - ), - 16: Field( - name='power_setting', - type=FIELD_TYPES['display_power'], - def_num=16, - ), - 17: Field( - name='activity_class', - type=FIELD_TYPES['activity_class'], - def_num=17, - ), - 18: Field( - name='position_setting', - type=FIELD_TYPES['display_position'], - def_num=18, - ), - 21: Field( - name='temperature_setting', - type=FIELD_TYPES['display_measure'], - def_num=21, - ), - 22: Field( - name='local_id', - type=FIELD_TYPES['user_local_id'], - def_num=22, - ), - 23: Field( - name='global_id', - type=BASE_TYPES[0x0D], # byte - def_num=23, - ), - 28: Field( # Typical wake time - name='wake_time', - type=FIELD_TYPES['localtime_into_day'], - def_num=28, - ), - 29: Field( # Typical bed time - name='sleep_time', - type=FIELD_TYPES['localtime_into_day'], - def_num=29, - ), - 30: Field( - name='height_setting', - type=FIELD_TYPES['display_measure'], - def_num=30, - ), - 31: Field( # User defined running step length set to 0 for auto length - name='user_running_step_length', - type=BASE_TYPES[0x84], # uint16 - def_num=31, - scale=1000, - units='m', - ), - 32: Field( # User defined walking step length set to 0 for auto length - name='user_walking_step_length', - type=BASE_TYPES[0x84], # uint16 - def_num=32, - scale=1000, - units='m', - ), - 47: Field( - name='depth_setting', - type=FIELD_TYPES['display_measure'], - def_num=47, - ), - 49: Field( - name='dive_count', - type=BASE_TYPES[0x86], # uint32 - def_num=49, - ), - 254: Field( - name='message_index', - type=FIELD_TYPES['message_index'], - def_num=254, - ), - }, - ), - - - # ********************** Sport Settings File Messages ********************** - 7: MessageType( - name='zones_target', - mesg_num=7, - fields={ - 1: Field( - name='max_heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=1, - ), - 2: Field( - name='threshold_heart_rate', - type=BASE_TYPES[0x02], # uint8 - def_num=2, - ), - 3: Field( - name='functional_threshold_power', - type=BASE_TYPES[0x84], # uint16 - def_num=3, - ), - 5: Field( - name='hr_calc_type', - type=FIELD_TYPES['hr_zone_calc'], - def_num=5, - ), - 7: Field( - name='pwr_calc_type', - type=FIELD_TYPES['pwr_zone_calc'], - def_num=7, - ), - }, - ), - - - # ************************** Totals File Messages ************************** - 33: MessageType( - name='totals', - mesg_num=33, - fields={ - 0: Field( # Excludes pauses - name='timer_time', - type=BASE_TYPES[0x86], # uint32 - def_num=0, - units='s', - ), - 1: Field( - name='distance', - type=BASE_TYPES[0x86], # uint32 - def_num=1, - units='m', + 19: Field( + name='secondary_target_type', + type=FIELD_TYPES['wkt_step_target'], + def_num=19, ), - 2: Field( - name='calories', + 20: Field( + name='secondary_target_value', type=BASE_TYPES[0x86], # uint32 - def_num=2, - units='kcal', - ), - 3: Field( - name='sport', - type=FIELD_TYPES['sport'], - def_num=3, + def_num=20, + subfields=( + SubField( # Zone (1-?); Custom = 0; + name='secondary_target_cadence_zone', + def_num=20, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='cadence', + raw_value=3, + ), + ), + ), + SubField( # hr zone (1-5);Custom =0; + name='secondary_target_hr_zone', + def_num=20, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='heart_rate', + raw_value=1, + ), + ), + ), + SubField( # Power Zone ( 1-7); Custom = 0; + name='secondary_target_power_zone', + def_num=20, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='power', + raw_value=4, + ), + ), + ), + SubField( # speed zone (1-10);Custom =0; + name='secondary_target_speed_zone', + def_num=20, + type=BASE_TYPES[0x86], # uint32 + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='speed', + raw_value=0, + ), + ), + ), + SubField( + name='secondary_target_stroke_type', + def_num=20, + type=FIELD_TYPES['swim_stroke'], + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='swim_stroke', + raw_value=11, + ), + ), + ), + ), ), - 4: Field( # Includes pauses - name='elapsed_time', + 21: Field( + name='secondary_custom_target_value_low', type=BASE_TYPES[0x86], # uint32 - def_num=4, - units='s', - ), - 5: Field( - name='sessions', - type=BASE_TYPES[0x84], # uint16 - def_num=5, + def_num=21, + subfields=( + SubField( + name='secondary_custom_target_cadence_low', + def_num=21, + type=BASE_TYPES[0x86], # uint32 + units='rpm', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='cadence', + raw_value=3, + ), + ), + ), + SubField( + name='secondary_custom_target_heart_rate_low', + def_num=21, + type=FIELD_TYPES['workout_hr'], + units='% or bpm', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='heart_rate', + raw_value=1, + ), + ), + ), + SubField( + name='secondary_custom_target_power_low', + def_num=21, + type=FIELD_TYPES['workout_power'], + units='% or watts', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='power', + raw_value=4, + ), + ), + ), + SubField( + name='secondary_custom_target_speed_low', + def_num=21, + type=BASE_TYPES[0x86], # uint32 + scale=1000, + units='m/s', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='speed', + raw_value=0, + ), + ), + ), + ), ), - 6: Field( - name='active_time', + 22: Field( + name='secondary_custom_target_value_high', type=BASE_TYPES[0x86], # uint32 - def_num=6, - units='s', - ), - 9: Field( - name='sport_index', - type=BASE_TYPES[0x02], # uint8 - def_num=9, + def_num=22, + subfields=( + SubField( + name='secondary_custom_target_cadence_high', + def_num=22, + type=BASE_TYPES[0x86], # uint32 + units='rpm', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='cadence', + raw_value=3, + ), + ), + ), + SubField( + name='secondary_custom_target_heart_rate_high', + def_num=22, + type=FIELD_TYPES['workout_hr'], + units='% or bpm', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='heart_rate', + raw_value=1, + ), + ), + ), + SubField( + name='secondary_custom_target_power_high', + def_num=22, + type=FIELD_TYPES['workout_power'], + units='% or watts', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='power', + raw_value=4, + ), + ), + ), + SubField( + name='secondary_custom_target_speed_high', + def_num=22, + type=BASE_TYPES[0x86], # uint32 + scale=1000, + units='m/s', + ref_fields=( + ReferenceField( + name='secondary_target_type', + def_num=19, + value='speed', + raw_value=0, + ), + ), + ), + ), ), - 253: FIELD_TYPE_TIMESTAMP, 254: Field( name='message_index', type=FIELD_TYPES['message_index'], @@ -12030,136 +16620,72 @@ ), }, ), - - - # *********************** Weight Scale File Messages *********************** - 30: MessageType( - name='weight_scale', - mesg_num=30, + 158: MessageType( + name='workout_session', + mesg_num=158, fields={ 0: Field( - name='weight', - type=FIELD_TYPES['weight'], + name='sport', + type=FIELD_TYPES['sport'], def_num=0, - scale=100, - units='kg', ), 1: Field( - name='percent_fat', - type=BASE_TYPES[0x84], # uint16 + name='sub_sport', + type=FIELD_TYPES['sub_sport'], def_num=1, - scale=100, - units='%', ), 2: Field( - name='percent_hydration', + name='num_valid_steps', type=BASE_TYPES[0x84], # uint16 def_num=2, - scale=100, - units='%', ), 3: Field( - name='visceral_fat_mass', + name='first_step_index', type=BASE_TYPES[0x84], # uint16 def_num=3, - scale=100, - units='kg', ), 4: Field( - name='bone_mass', + name='pool_length', type=BASE_TYPES[0x84], # uint16 def_num=4, scale=100, - units='kg', + units='m', ), 5: Field( - name='muscle_mass', - type=BASE_TYPES[0x84], # uint16 + name='pool_length_unit', + type=FIELD_TYPES['display_measure'], def_num=5, - scale=100, - units='kg', - ), - 7: Field( - name='basal_met', - type=BASE_TYPES[0x84], # uint16 - def_num=7, - scale=4, - units='kcal/day', - ), - 8: Field( - name='physique_rating', - type=BASE_TYPES[0x02], # uint8 - def_num=8, - ), - 9: Field( # ~4kJ per kcal, 0.25 allows max 16384 kcal - name='active_met', - type=BASE_TYPES[0x84], # uint16 - def_num=9, - scale=4, - units='kcal/day', - ), - 10: Field( - name='metabolic_age', - type=BASE_TYPES[0x02], # uint8 - def_num=10, - units='years', - ), - 11: Field( - name='visceral_fat_rating', - type=BASE_TYPES[0x02], # uint8 - def_num=11, ), - 12: Field( # Associates this weight scale message to a user. This corresponds to the index of the user profile message in the weight scale file. - name='user_profile_index', + 254: Field( + name='message_index', type=FIELD_TYPES['message_index'], - def_num=12, + def_num=254, ), - 253: FIELD_TYPE_TIMESTAMP, }, ), - - - # ************************* Workout File Messages ************************** - 26: MessageType( - name='workout', - mesg_num=26, + 264: MessageType( + name='exercise_title', + mesg_num=264, fields={ - 4: Field( - name='sport', - type=FIELD_TYPES['sport'], - def_num=4, - ), - 5: Field( - name='capabilities', - type=FIELD_TYPES['workout_capabilities'], - def_num=5, + 0: Field( + name='exercise_category', + type=FIELD_TYPES['exercise_category'], + def_num=0, ), - 6: Field( # number of valid steps - name='num_valid_steps', + 1: Field( + name='exercise_name', type=BASE_TYPES[0x84], # uint16 - def_num=6, + def_num=1, ), - 8: Field( - name='wkt_name', + 2: Field( + name='wkt_step_name', type=BASE_TYPES[0x07], # string - def_num=8, - ), - 11: Field( - name='sub_sport', - type=FIELD_TYPES['sub_sport'], - def_num=11, - ), - 14: Field( - name='pool_length', - type=BASE_TYPES[0x84], # uint16 - def_num=14, - scale=100, - units='m', + def_num=2, ), - 15: Field( - name='pool_length_unit', - type=FIELD_TYPES['display_measure'], - def_num=15, + 254: Field( + name='message_index', + type=FIELD_TYPES['message_index'], + def_num=254, ), }, ),