fit_rust/protocol/
message_type.rs

1use crate::protocol::io::write_bin;
2use binrw::BinResult;
3
4macro_rules! enum_from_primitive {
5    ($typ:ident, $t:ty, $($name:ident = $value:expr),+,) => {
6        #[derive(Debug, Copy, Clone, PartialEq)]
7        #[repr($t)]
8        pub enum $typ {
9            $($name = $value),+,
10        }
11
12        impl $typ {
13            pub fn from_primitive(value: $t) -> Option<Self> {
14                match value {
15                    $(x if x == $typ::$name as $t => Some($typ::$name),)+
16                    _ => None,
17                }
18            }
19
20            pub fn to_primitive(self) -> $t {
21                self as $t
22            }
23        }
24    };
25}
26
27// an enum of all defined messages in the Fit SDK
28enum_from_primitive! {
29    MessageType, u16,
30    FileId = 0,
31    Capabilities = 1,
32    DeviceSettings = 2,
33    UserProfile = 3,
34    HrmProfile = 4,
35    SdmProfile = 5,
36    BikeProfile = 6,
37    ZonesTarget = 7,
38    HrZone = 8,
39    PowerZone = 9,
40    MetZone = 10,
41    Sport = 12,
42    Goal = 15,
43    Session = 18,
44    Lap = 19,
45    Record = 20,
46    Event = 21,
47    DeviceInfo = 23,
48    Workout = 26,
49    WorkoutStep = 27,
50    Schedule = 28,
51    WeightScale = 30,
52    Course = 31,
53    CoursePoint = 32,
54    Totals = 33,
55    Activity = 34,
56    Software = 35,
57    FileCapabilities = 37,
58    MesgCapabilities = 38,
59    FieldCapabilities = 39,
60    FileCreator = 49,
61    BloodPressure = 51,
62    SpeedZone = 53,
63    Monitoring = 55,
64    TrainingFile = 72,
65    Hrv = 78,
66    AntRx = 80,
67    AntTx = 81,
68    AntChannelId = 82,
69    Length = 101,
70    MonitoringInfo = 103,
71    Pad = 105,
72    SlaveDevice = 106,
73    Connectivity = 127,
74    WeatherConditions = 128,
75    WeatherAlert = 129,
76    CadenceZone = 131,
77    Hr = 132,
78    SegmentLap = 142,
79    MemoGlob = 145,
80    SegmentId = 148,
81    SegmentLeaderboardEntry = 149,
82    SegmentPoint = 150,
83    SegmentFile = 151,
84    WorkoutSession = 158,
85    WatchfaceSettings = 159,
86    GpsMetadata = 160,
87    CameraEvent = 161,
88    TimestampCorrelation = 162,
89    GyroscopeData = 164,
90    AccelerometerData = 165,
91    ThreeDSensorCalibration = 167,
92    VideoFrame = 169,
93    ObdiiData = 174,
94    NmeaSentence = 177,
95    AviationAttitude = 178,
96    Video = 184,
97    VideoTitle = 185,
98    VideoDescription = 186,
99    VideoClip = 187,
100    OhrSettings = 188,
101    ExdScreenConfiguration = 200,
102    ExdDataFieldConfiguration = 201,
103    ExdDataConceptConfiguration = 202,
104    FieldDescription = 206,
105    DeveloperDataId = 207,
106    MagnetometerData = 208,
107    BarometerData = 209,
108    OneDSensorCalibration = 210,
109    MonitoringHrData = 211,
110    TimeInZone = 216,
111    Set = 225,
112    StressLevel = 227,
113    MaxMetData = 229,
114    DiveSettings = 258,
115    DiveGas = 259,
116    DiveAlarm = 262,
117    ExerciseTitle = 264,
118    DiveSummary = 268,
119    Spo2Data = 269,
120    SleepLevel = 275,
121    Jump = 285,
122    BeatIntervals = 290,
123    RespirationRate = 297,
124    Split = 312,
125    ClimbPro = 317,
126    TankUpdate = 319,
127    TankSummary = 323,
128    SleepAssessment = 346,
129    HrvStatusSummary = 370,
130    HrvValue = 371,
131    DeviceAuxBatteryInfo = 375,
132    DiveApneaAlarm = 393,
133    MfgRangeMin = 0xFF00,
134    MfgRangeMax = 0xFFFE,
135    None = 0xFFFF,
136}
137
138#[allow(unused)]
139#[binrw::writer(writer, endian)]
140pub fn write_message_type(value: &MessageType) -> BinResult<()> {
141    write_bin(writer, value.to_primitive(), endian)?;
142    Ok(())
143}
144
145#[binrw::parser()]
146pub fn parse_message_type(value: u16) -> BinResult<MessageType> {
147    if let Some(message_type) = MessageType::from_primitive(value) {
148        return Ok(message_type);
149    } else {
150        match value {
151            0xFF00..=0xFFFE => Ok(MessageType::MfgRangeMin),
152            _ => Ok(MessageType::None),
153        }
154    }
155}