#!/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, 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, { 0x00: Int8sl, 0x01: Int8ul, 0x02: Int16sl, 0x03: Int16ul, 0x04: Int32sl, 0x05: Int32ul, 0x06: Int64sl, 0x07: Int64ul, 0x08: Float32l, 0x09: Float64l, 0x0A: NullTerminated(GreedyRange(Int8ul)), 0x0B: 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, ), }) 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) )