132 lines
3.1 KiB
Python
132 lines
3.1 KiB
Python
|
|
#!/usr/bin/env python
|
||
|
|
|
||
|
|
from construct import *
|
||
|
|
|
||
|
|
BLOCK_TYPE = Enum(Int8ul,
|
||
|
|
RESERVED = 0x00,
|
||
|
|
ARBITRARY_TIMESTAMP = 0x01,
|
||
|
|
CONSTANT_FREQUENCY = 0x02,
|
||
|
|
)
|
||
|
|
|
||
|
|
SAMPLE_TYPE = Enum(Int16ul,
|
||
|
|
RESERVED = 0x0000,
|
||
|
|
TEMPERATURE = 0x0001,
|
||
|
|
ACCELERATION = 0x0002,
|
||
|
|
ANGULAR_RATE = 0x0003,
|
||
|
|
VOLTAGE = 0x0004,
|
||
|
|
ECG = 0x0005,
|
||
|
|
HUMIDITY = 0x0006,
|
||
|
|
PRESSURE = 0x0007,
|
||
|
|
MAGNETIC_FLUX_DENSITY = 0x0008,
|
||
|
|
BINARY_DATA = 0x0009,
|
||
|
|
|
||
|
|
CUSTOM = 0xF000,
|
||
|
|
)
|
||
|
|
|
||
|
|
resd_header = Struct(
|
||
|
|
"magic" / Const(b"RESD"),
|
||
|
|
"version" / Int8ul,
|
||
|
|
"reserved" / Padding(3)
|
||
|
|
)
|
||
|
|
|
||
|
|
blob = Struct(
|
||
|
|
"size" / Rebuild(Int32ul, len_(this.data)),
|
||
|
|
"data" / Int8ul[this.size],
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_metadata_item = Struct(
|
||
|
|
"key" / NullTerminated(GreedyRange(Int8ub)),
|
||
|
|
"type" / Int8ul,
|
||
|
|
"value" / Switch(this.type,
|
||
|
|
{
|
||
|
|
0x01: Int8sl,
|
||
|
|
0x02: Int8ul,
|
||
|
|
0x03: Int16sl,
|
||
|
|
0x04: Int16ul,
|
||
|
|
0x05: Int32sl,
|
||
|
|
0x06: Int32ul,
|
||
|
|
0x07: Int64sl,
|
||
|
|
0x08: Int64ul,
|
||
|
|
0x09: Float32l,
|
||
|
|
0x0A: Float64l,
|
||
|
|
0x0B: NullTerminated(GreedyRange(Int8ul)),
|
||
|
|
0x0C: blob,
|
||
|
|
}),
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_metadata = Struct(
|
||
|
|
"size" / Int64ul,
|
||
|
|
"items" / FixedSized(this.size, GreedyRange(data_block_metadata_item)),
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_sample = lambda sample_type: Switch(sample_type, {
|
||
|
|
"TEMPERATURE": Int32sl,
|
||
|
|
"ACCELERATION": Struct(
|
||
|
|
"x" / Int32sl,
|
||
|
|
"y" / Int32sl,
|
||
|
|
"z" / Int32sl,
|
||
|
|
),
|
||
|
|
"ANGULAR_RATE": Struct(
|
||
|
|
"x" / Int32sl,
|
||
|
|
"y" / Int32sl,
|
||
|
|
"z" / Int32sl,
|
||
|
|
),
|
||
|
|
"VOLTAGE": Int32ul,
|
||
|
|
"ECG": Int32sl,
|
||
|
|
"HUMIDITY": Int32ul,
|
||
|
|
"PRESSURE": Int64ul,
|
||
|
|
"MAGNETIC_FLUX_DENSITY": Struct(
|
||
|
|
"x" / Int32sl,
|
||
|
|
"y" / Int32sl,
|
||
|
|
"z" / Int32sl,
|
||
|
|
),
|
||
|
|
"BINARY_DATA": blob,
|
||
|
|
})
|
||
|
|
|
||
|
|
data_block_sample_arbitrary = lambda sample_type: Struct(
|
||
|
|
"timestamp" / Int64ul,
|
||
|
|
"sample" / data_block_sample(sample_type)
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_sample_arbitrary_subheader = Struct(
|
||
|
|
"start_time" / Int64ul,
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_sample_frequency = lambda sample_type: Struct(
|
||
|
|
"sample" / data_block_sample(sample_type)
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_sample_frequency_subheader = Struct(
|
||
|
|
"start_time" / Int64ul,
|
||
|
|
"period" / Int64ul,
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block_sample_single = lambda type_, sample_type: Switch(type_, {
|
||
|
|
"ARBITRARY_TIMESTAMP": data_block_sample_arbitrary(sample_type),
|
||
|
|
"CONSTANT_FREQUENCY": data_block_sample_frequency(sample_type),
|
||
|
|
})
|
||
|
|
|
||
|
|
data_block_subheader = Switch(this.header.block_type, {
|
||
|
|
"ARBITRARY_TIMESTAMP": data_block_sample_arbitrary_subheader,
|
||
|
|
"CONSTANT_FREQUENCY": data_block_sample_frequency_subheader
|
||
|
|
})
|
||
|
|
|
||
|
|
data_block_header = Struct(
|
||
|
|
"block_type" / BLOCK_TYPE,
|
||
|
|
"sample_type" / SAMPLE_TYPE,
|
||
|
|
"channel_id" / Int16ul,
|
||
|
|
"data_size" / Int64ul,
|
||
|
|
)
|
||
|
|
|
||
|
|
data_block = Struct(
|
||
|
|
"header" / data_block_header,
|
||
|
|
"subheader" / data_block_subheader,
|
||
|
|
"metadata" / data_block_metadata,
|
||
|
|
"samples" / GreedyRange(data_block_sample_single(this.header.block_type, this._.header.sample_type))
|
||
|
|
)
|
||
|
|
|
||
|
|
resd = Struct(
|
||
|
|
"header" / resd_header,
|
||
|
|
"blocks" / GreedyRange(data_block)
|
||
|
|
)
|