Clean up code, refactoring, begin to read more than 1 row
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
module FIT
|
module FIT
|
||||||
|
|
||||||
export read_file
|
export read_file
|
||||||
|
|
||||||
include("file.jl")
|
include("file.jl")
|
||||||
|
|||||||
+50
-30
@@ -19,14 +19,19 @@ struct FITHeader
|
|||||||
crc::AbstractVector{<:Real}
|
crc::AbstractVector{<:Real}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@enum RecordType begin
|
||||||
|
definition = 1
|
||||||
|
data = 2
|
||||||
|
timestamp = 3
|
||||||
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
RecordHeader
|
RecordHeader
|
||||||
|
|
||||||
Contains the header byte for a record row
|
Contains the header byte for a record row
|
||||||
"""
|
"""
|
||||||
mutable struct RecordHeader
|
mutable struct RecordHeader
|
||||||
definition::Bool
|
type::RecordType
|
||||||
data::Bool
|
|
||||||
local_mesg_type::Int64
|
local_mesg_type::Int64
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -63,12 +68,12 @@ mutable struct FITFileReader
|
|||||||
header::Union{FITHeader, Nothing}
|
header::Union{FITHeader, Nothing}
|
||||||
body::Union{Vector{DataRecord}, Nothing}
|
body::Union{Vector{DataRecord}, Nothing}
|
||||||
mesg_map::Dict{Real, AbstractString}
|
mesg_map::Dict{Real, AbstractString}
|
||||||
|
next_row_sz::Int64
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
blank_file(fp::AbstractString) = FITFileReader(fp, nothing, 0, nothing, nothing, Dict())
|
blank_file(fp::AbstractString) = FITFileReader(fp, nothing, 0, nothing, nothing, Dict(), 0)
|
||||||
blank_row() = DataRecord(nothing)
|
blank_row() = DataRecord(nothing)
|
||||||
blank_header_byte() = RecordHeader(false, false, 0)
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
open_fit_file!(f::FITFileReader)
|
open_fit_file!(f::FITFileReader)
|
||||||
@@ -123,11 +128,16 @@ end
|
|||||||
Decode the header byte, determine if the record is a definition, data, or timestamp.
|
Decode the header byte, determine if the record is a definition, data, or timestamp.
|
||||||
"""
|
"""
|
||||||
function decode_header(v::Vector{UInt8})::RecordHeader
|
function decode_header(v::Vector{UInt8})::RecordHeader
|
||||||
record = blank_header_byte()
|
type = if v[7] == 1
|
||||||
record.definition = v[7] === 0x01
|
timestamp
|
||||||
record.data = !record.definition
|
elseif v[6] == 1
|
||||||
record.local_mesg_type = sum_bits(v[1:4])
|
definition
|
||||||
record
|
else
|
||||||
|
data
|
||||||
|
end
|
||||||
|
|
||||||
|
local_mesg_type = sum_bits(v[1:4])
|
||||||
|
RecordHeader(type, local_mesg_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -144,6 +154,10 @@ function parse_field(mesg_type::AbstractString, bytes::Vector{UInt8})::FieldDefi
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_row_size(field_definitions::Vector{FieldDefinition})::Int64
|
||||||
|
sum([def.sz_bytes for def ∈ field_definitions])
|
||||||
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{DefinitionBody, DataBody}
|
read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{DefinitionBody, DataBody}
|
||||||
|
|
||||||
@@ -152,29 +166,36 @@ Using f, read the appropriate message body given the hdr (which tells us if this
|
|||||||
function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{DefinitionBody, DataBody}
|
function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{DefinitionBody, DataBody}
|
||||||
# Read the definition record, return the body
|
# Read the definition record, return the body
|
||||||
if hdr.definition
|
if hdr.definition
|
||||||
# Read the fixed 5 bytes first.
|
# Read all bytes first
|
||||||
def_header_bytes = read_bytes!(f, 5)
|
header_bytes = read_bytes!(f, 5)
|
||||||
global_mesg_type = get_mesg_num_string(byte_vec_to_int(def_header_bytes[3:4]))
|
header_field_definitions = read_bytes!(f, header_bytes[end] * 3) # sz * field size
|
||||||
def_header_fields = read_bytes!(f, def_header_bytes[end] * 3)
|
header_developer_flag = read_bytes!(f, 1)
|
||||||
|
if header_developer_flag[1] > 0x00
|
||||||
# Parse the field. global_mesg_type needed to decode the field number description
|
header_developer_fields = read_bytes!(f, header_developer_flag[1] * 3)
|
||||||
field_definitions = [parse_field(global_mesg_type, def_header_fields[i:i+2]) for i ∈ 1:3:length(def_header_fields)]
|
else
|
||||||
|
header_developer_fields::Vector{UInt8} = []
|
||||||
# See if there is developer data
|
|
||||||
def_header_developer_flag = read_bytes!(f, 1)
|
|
||||||
if def_header_developer_flag[1] > 0x00
|
|
||||||
def_header_developer_fields = read_bytes!(f, def_header_developer_flag * 3)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Parse the bytes
|
||||||
|
global_mesg_type = get_mesg_num_string(byte_vec_to_int(header_bytes[3:4]))
|
||||||
|
field_definitions = [parse_field(global_mesg_type, header_field_definitions[i:i+2]) for i ∈ 1:3:length(header_field_definitions)]
|
||||||
|
developer_field_definitions = [parse_field(global_mesg_type, header_developer_fields[1:1+2]) for i ∈ 1:3:length(header_developer_fields)]
|
||||||
|
|
||||||
|
# Get the total row size from parsing the fields.
|
||||||
|
row_sz = sum(get_row_size.([field_definitions, developer_field_definitions]))
|
||||||
|
|
||||||
# Associate the global message type with this local message type.
|
# Associate the global message type with this local message type.
|
||||||
f.mesg_map[hdr.local_mesg_type] = global_mesg_type
|
f.mesg_map[hdr.local_mesg_type] = global_mesg_type
|
||||||
|
f.next_row_sz = row_sz
|
||||||
|
|
||||||
DefinitionBody(
|
DefinitionBody(
|
||||||
def_header_bytes[2] == 0 ? "littleendian" : "bigendian",
|
header_bytes[2] == 0 ? "littleendian" : "bigendian",
|
||||||
global_mesg_type,
|
global_mesg_type,
|
||||||
def_header_bytes[end],
|
header_bytes[end],
|
||||||
field_definitions
|
field_definitions
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
row_bytes = read_bytes!(f, f.next_row_sz)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -186,24 +207,23 @@ Read all the data record messages.
|
|||||||
function read_records!(f::FITFileReader)
|
function read_records!(f::FITFileReader)
|
||||||
if f.bytes_read < 12 || f.bytes_read > 14
|
if f.bytes_read < 12 || f.bytes_read > 14
|
||||||
throw("invalid header read, not within header size")
|
throw("invalid header read, not within header size")
|
||||||
|
elseif isnothing(f.header)
|
||||||
|
throw("cant read FIT file, no header")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read header byte - decode
|
# Loop through bytes_read until done
|
||||||
|
while f.bytes_read < f.header.size
|
||||||
|
# Read header byte.
|
||||||
header_bits = bit_vector(read_bytes!(f, 1); little_endian=true)
|
header_bits = bit_vector(read_bytes!(f, 1); little_endian=true)
|
||||||
header = decode_header(header_bits)
|
header = decode_header(header_bits)
|
||||||
|
|
||||||
# Read the record content
|
|
||||||
|
|
||||||
record = DataRecord(header, read_record_content!(f, header))
|
record = DataRecord(header, read_record_content!(f, header))
|
||||||
|
|
||||||
# Push record to the body.
|
|
||||||
if isnothing(f.body)
|
if isnothing(f.body)
|
||||||
f.body = [record]
|
f.body = [record]
|
||||||
else
|
else
|
||||||
push!(f.body, record)
|
push!(f.body, record)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
record
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function read_file(filepath::AbstractString)::FITFileReader
|
function read_file(filepath::AbstractString)::FITFileReader
|
||||||
|
|||||||
Reference in New Issue
Block a user