Reading definition headers
parent
32b806200d
commit
79c21af5dd
13
src/bytes.jl
13
src/bytes.jl
|
@ -1,6 +1,6 @@
|
|||
module bytes
|
||||
|
||||
export byte_vec_to_int, byte_vec_to_string, bit_at, bit_vector
|
||||
export byte_vec_to_int, byte_vec_to_string, bit_at, bit_vector, sum_bits
|
||||
|
||||
"""
|
||||
read_data_size(size::Vector{UInt8})::Real
|
||||
|
@ -53,5 +53,16 @@ function bit_vector(byte_vector::Vector{UInt8}; little_endian=false)::Vector{UIn
|
|||
reduce(vcat, vecs)
|
||||
end
|
||||
|
||||
"""
|
||||
sum_bits(bit_vector::Vector{UInt8})::Int64
|
||||
|
||||
Sum the bits found in bit_vector, return a value in Int64, Calculate the value of
|
||||
each bit along the way.
|
||||
"""
|
||||
function sum_bits(bit_vector::Vector{UInt8})::Int64
|
||||
rev = reverse(bit_vector)
|
||||
sum([rev[i] * (2 ^ (i - 1)) for i ∈ eachindex(rev)])
|
||||
end
|
||||
|
||||
end
|
||||
# byte_vec_to_string(UInt8.(collect("ABC")))
|
||||
|
|
89
src/file.jl
89
src/file.jl
|
@ -1,8 +1,11 @@
|
|||
module file
|
||||
|
||||
export FITFile, read_file
|
||||
import Base.show
|
||||
|
||||
export FITFile, read_file, DataRecord
|
||||
|
||||
include("bytes.jl"); using .bytes
|
||||
include("mesg_num.jl"); using .mesg_num
|
||||
|
||||
|
||||
HEADER_SZ = 14
|
||||
|
@ -16,9 +19,34 @@ struct FITHeader
|
|||
crc::AbstractVector{<:Real}
|
||||
end
|
||||
|
||||
mutable struct DataRecord
|
||||
"""
|
||||
RecordHeader
|
||||
|
||||
Contains the header byte for a record row
|
||||
"""
|
||||
mutable struct RecordHeader
|
||||
definition::Bool
|
||||
data::Bool
|
||||
local_mesg_type::Int64
|
||||
end
|
||||
|
||||
mutable struct DefinitionBody
|
||||
architecture::AbstractString
|
||||
global_mesg_type::AbstractString # Read from mesg_num.jl using the bytes in this field.
|
||||
num_fields::UInt8
|
||||
end
|
||||
|
||||
mutable struct DataBody
|
||||
end
|
||||
|
||||
"""
|
||||
DataRecord
|
||||
|
||||
Represents a DataRecord within the Garmin file.
|
||||
"""
|
||||
mutable struct DataRecord
|
||||
hdr::Union{RecordHeader, Nothing}
|
||||
body::Union{DefinitionBody, DataBody}
|
||||
end
|
||||
|
||||
mutable struct FITFileReader
|
||||
|
@ -31,7 +59,8 @@ end
|
|||
|
||||
|
||||
blank_file(fp::AbstractString) = FITFileReader(fp, nothing, 0, nothing, nothing)
|
||||
blank_row() = DataRecord(false, false)
|
||||
blank_row() = DataRecord(nothing)
|
||||
blank_header_byte() = RecordHeader(false, false, 0)
|
||||
|
||||
"""
|
||||
open_fit_file!(f::FITFileReader)
|
||||
|
@ -81,15 +110,42 @@ function read_header!(f::FITFileReader)
|
|||
end
|
||||
|
||||
"""
|
||||
decode_header(v::Vector{UInt8})
|
||||
decode_header(v::Vector{UInt8})::RecordHeader
|
||||
|
||||
Decode the header byte, determine if the record is a definition, data, or timestamp.
|
||||
"""
|
||||
function decode_header(v::Vector{UInt8})::DataRecord
|
||||
record = blank_row()
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
"""
|
||||
read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{DefinitionBody, DataBody}
|
||||
|
||||
Using f, read the appropriate message body given the hdr (which tells us if this is def or data)
|
||||
"""
|
||||
function read_record_content!(f::FITFileReader, hdr::RecordHeader)::Union{DefinitionBody, DataBody}
|
||||
# Read the definition record, return the body
|
||||
if hdr.definition
|
||||
# Read the fixed 5 bytes first.
|
||||
def_header_bytes = read_bytes!(f, 5)
|
||||
def_header_fields = read_bytes!(f, def_header_bytes[end] * 3)
|
||||
|
||||
# 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
|
||||
|
||||
DefinitionBody(
|
||||
def_header_bytes[2] == 0 ? "littleendian" : "bigendian",
|
||||
get_mesg_num_string(byte_vec_to_int(def_header_bytes[3:4])),
|
||||
def_header_bytes[end]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -104,7 +160,11 @@ function read_records!(f::FITFileReader)
|
|||
|
||||
# Read header byte - decode
|
||||
header_bits = bit_vector(read_bytes!(f, 1); little_endian=true)
|
||||
record = decode_header(header_bits)
|
||||
header = decode_header(header_bits)
|
||||
|
||||
# Read the record content
|
||||
|
||||
record = DataRecord(header, read_record_content!(f, header))
|
||||
|
||||
# Push record to the body.
|
||||
if isnothing(f.body)
|
||||
|
@ -132,4 +192,17 @@ function read_file(filepath::AbstractString)::FITFileReader
|
|||
f
|
||||
end
|
||||
|
||||
function show(io::IO, hdr::RecordHeader)
|
||||
type = hdr.definition ? "Definition" : "Data"
|
||||
println(io, "Header($(type), local_message_type=$(hdr.local_mesg_type))")
|
||||
end
|
||||
|
||||
function show(io::IO, ffr::FITFileReader)
|
||||
println(io, "FITFileReader($(ffr.filepath), bytes_read=$(ffr.bytes_read), header=$(ffr.header), body=$(ffr.body))")
|
||||
end
|
||||
|
||||
function show(io::IO, defbody::DefinitionBody)
|
||||
println(io, "DefinitionBody(arch=$(defbody.architecture), global_type=$(defbody.global_mesg_type), num_fields=$(defbody.num_fields))")
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue