message numbers are included in each message type.

Defines the field def numbers for FILE_ID
This commit is contained in:
2023-04-26 08:47:21 -04:00
parent 7726241012
commit f230d2cbe6
3 changed files with 40 additions and 14 deletions
+1 -3
View File
@@ -8,6 +8,4 @@ using .file
end end
using .FIT using .FIT
open("test.FIT", "r") do f ffr = FIT.read_file("test.FIT")
h = FIT.read_header(f)
end
+8 -8
View File
@@ -31,7 +31,7 @@ mutable struct RecordHeader
end end
struct FieldDefinition struct FieldDefinition
number::UInt8 type::AbstractString
sz_bytes::UInt8 sz_bytes::UInt8
base_type::Type # TODO: This needs to be translated into an actual base type. base_type::Type # TODO: This needs to be translated into an actual base type.
end end
@@ -126,7 +126,7 @@ function decode_header(v::Vector{UInt8})::RecordHeader
record = blank_header_byte() record = blank_header_byte()
record.definition = v[7] === 0x01 record.definition = v[7] === 0x01
record.data = !record.definition record.data = !record.definition
record.local_mesg_type = sum_bits(v[end-3:end]) record.local_mesg_type = sum_bits(v[1:4])
record record
end end
@@ -135,9 +135,10 @@ end
Parse a field definition in the definition message into a struct Parse a field definition in the definition message into a struct
""" """
function parse_field(bytes::Vector{UInt8})::FieldDefinition function parse_field(mesg_type::AbstractString, bytes::Vector{UInt8})::FieldDefinition
# TODO the first byte of the field definition, the field num, is definiedre-defined by each mesg definitionn
FieldDefinition( FieldDefinition(
bytes[1], get_field_description(mesg_type, bytes[1]),
bytes[2], bytes[2],
get_base_type(bytes[3]) get_base_type(bytes[3])
) )
@@ -153,11 +154,11 @@ function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{Defini
if hdr.definition if hdr.definition
# Read the fixed 5 bytes first. # Read the fixed 5 bytes first.
def_header_bytes = read_bytes!(f, 5) def_header_bytes = read_bytes!(f, 5)
global_mesg_type = get_mesg_num_string(byte_vec_to_int(def_header_bytes[3:4]))
def_header_fields = read_bytes!(f, def_header_bytes[end] * 3) def_header_fields = read_bytes!(f, def_header_bytes[end] * 3)
# Should always be a multiple of 3 # Parse the field. global_mesg_type needed to decode the field number description
# TODO: There is a missing byte here that complicates parsing field_definitions = [parse_field(global_mesg_type, def_header_fields[i:i+2]) for i 1:3:length(def_header_fields)]
field_definitions = [parse_field(def_header_fields[i:i+2]) for i 1:3:length(def_header_fields)]
# See if there is developer data # See if there is developer data
def_header_developer_flag = read_bytes!(f, 1) def_header_developer_flag = read_bytes!(f, 1)
@@ -166,7 +167,6 @@ function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{Defini
end end
# Associate the global message type with this local message type. # Associate the global message type with this local message type.
global_mesg_type = get_mesg_num_string(byte_vec_to_int(def_header_bytes[3:4]))
f.mesg_map[hdr.local_mesg_type] = global_mesg_type f.mesg_map[hdr.local_mesg_type] = global_mesg_type
DefinitionBody( DefinitionBody(
+31 -3
View File
@@ -2,7 +2,7 @@
module mesg_num module mesg_num
export get_mesg_num_string, get_field_definition_string export get_mesg_num_string, get_field_definition_string, get_mesg_num, get_field_description
FILE_ID = 0 FILE_ID = 0
CAPABILITIES = 1 CAPABILITIES = 1
@@ -138,14 +138,14 @@ MESG_NUM_MAP = Dict(
MONITORING => "MONITORING", MONITORING => "MONITORING",
TRAINING_FILE => "TRAINING_FILE", TRAINING_FILE => "TRAINING_FILE",
HRV => "HRV", HRV => "HRV",
ANT_RX => "ANT_RX", ANT_RX => "ANT_RX",
ANT_TX => "ANT_TX", ANT_TX => "ANT_TX",
ANT_CHANNEL_ID => "ANT_CHANNEL_ID", ANT_CHANNEL_ID => "ANT_CHANNEL_ID",
LENGTH => "LENGTH", LENGTH => "LENGTH",
MONITORING_INFO => "MONITORING_INFO", MONITORING_INFO => "MONITORING_INFO",
PAD => "PAD", PAD => "PAD",
SLAVE_DEVICE => "SLAVE_DEVICE", SLAVE_DEVICE => "SLAVE_DEVICE",
CONNECTIVITY => "CONNECTIVITY", CONNECTIVITY => "CONNECTIVITY",
WEATHER_CONDITIONS => "WEATHER_CONDITIONS", WEATHER_CONDITIONS => "WEATHER_CONDITIONS",
WEATHER_ALERT => "WEATHER_ALERT", WEATHER_ALERT => "WEATHER_ALERT",
CADENCE_ZONE => "CADENCE_ZONE", CADENCE_ZONE => "CADENCE_ZONE",
@@ -216,6 +216,16 @@ function get_mesg_num_string(mesg_num::Real)::Union{AbstractString,Nothing}
end end
end end
function get_mesg_num(mesg_type::AbstractString)::Union{Real,Nothing}
for (key, value) MESG_NUM_MAP
if value == mesg_type
return key
end
end
return nothing
end
FIELD_DEFINITION_MAP = Dict( FIELD_DEFINITION_MAP = Dict(
0xFF => "Invalid", 0xFF => "Invalid",
254 => "MessageIndex", 254 => "MessageIndex",
@@ -230,4 +240,22 @@ function get_field_definition_string(num::Real)::Union{AbstractString,Nothing}
end end
end end
FIELD_DESCRIPTIONS = Dict(FILE_ID => Dict(
0 => "type",
1 => "manufacturer",
2 => "product",
3 => "serial_number",
4 => "time_created",
5 => "number",
8 => "product_name"
))
function get_field_description(mesg_type::AbstractString, field_num::Real)::Union{AbstractString, Nothing}
try
FIELD_DESCRIPTIONS[get_mesg_num(mesg_type)][field_num]
catch
"nothing"
end
end
end end