message numbers are included in each message type.

Defines the field def numbers for FILE_ID
main
Jacob Windle 2023-04-26 08:47:21 -04:00
parent 7726241012
commit f230d2cbe6
3 changed files with 40 additions and 14 deletions

View File

@ -8,6 +8,4 @@ using .file
end
using .FIT
open("test.FIT", "r") do f
h = FIT.read_header(f)
end
ffr = FIT.read_file("test.FIT")

View File

@ -31,7 +31,7 @@ mutable struct RecordHeader
end
struct FieldDefinition
number::UInt8
type::AbstractString
sz_bytes::UInt8
base_type::Type # TODO: This needs to be translated into an actual base type.
end
@ -126,7 +126,7 @@ function decode_header(v::Vector{UInt8})::RecordHeader
record = blank_header_byte()
record.definition = v[7] === 0x01
record.data = !record.definition
record.local_mesg_type = sum_bits(v[end-3:end])
record.local_mesg_type = sum_bits(v[1:4])
record
end
@ -135,9 +135,10 @@ end
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(
bytes[1],
get_field_description(mesg_type, bytes[1]),
bytes[2],
get_base_type(bytes[3])
)
@ -153,11 +154,11 @@ function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{Defini
if hdr.definition
# Read the fixed 5 bytes first.
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)
# Should always be a multiple of 3
# TODO: There is a missing byte here that complicates parsing
field_definitions = [parse_field(def_header_fields[i:i+2]) for i 1:3:length(def_header_fields)]
# Parse the field. global_mesg_type needed to decode the field number description
field_definitions = [parse_field(global_mesg_type, def_header_fields[i:i+2]) for i 1:3:length(def_header_fields)]
# See if there is developer data
def_header_developer_flag = read_bytes!(f, 1)
@ -166,7 +167,6 @@ function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{Defini
end
# 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
DefinitionBody(

View File

@ -2,7 +2,7 @@
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
CAPABILITIES = 1
@ -138,14 +138,14 @@ MESG_NUM_MAP = Dict(
MONITORING => "MONITORING",
TRAINING_FILE => "TRAINING_FILE",
HRV => "HRV",
ANT_RX => "ANT_RX",
ANT_RX => "ANT_RX",
ANT_TX => "ANT_TX",
ANT_CHANNEL_ID => "ANT_CHANNEL_ID",
LENGTH => "LENGTH",
MONITORING_INFO => "MONITORING_INFO",
PAD => "PAD",
SLAVE_DEVICE => "SLAVE_DEVICE",
CONNECTIVITY => "CONNECTIVITY",
CONNECTIVITY => "CONNECTIVITY",
WEATHER_CONDITIONS => "WEATHER_CONDITIONS",
WEATHER_ALERT => "WEATHER_ALERT",
CADENCE_ZONE => "CADENCE_ZONE",
@ -216,6 +216,16 @@ function get_mesg_num_string(mesg_num::Real)::Union{AbstractString,Nothing}
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(
0xFF => "Invalid",
254 => "MessageIndex",
@ -230,4 +240,22 @@ function get_field_definition_string(num::Real)::Union{AbstractString,Nothing}
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