-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecoder.py
More file actions
89 lines (71 loc) · 3.93 KB
/
decoder.py
File metadata and controls
89 lines (71 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import struct
import re
import numpy as np
import argparse
def arg_parser():
parser = argparse.ArgumentParser(description="Peach Data File Analyzer")
#parser.add_argument("file_path",required=False, default="row005409-001049D", help="Path to the .peach-data file to analyze")
return parser.parse_args()
def analyze_peach_file(file_path):
print(f"--- Analyzing {file_path} ---")
with open(file_path
, 'rb') as f:
raw_data = f.read()
# 1. Extract ASCII strings to read metadata, settings, and event logs
# We look for continuous printable characters (length >= 5 to filter noise)
strings = re.findall(b'[a-zA-Z0-9_\-\. ]{5,}', raw_data)
print("\n[+] Extracted Metadata & Settings:")
# Print the first few readable strings (often contains boat/crew/setup info)
for s in strings[:15]:
print(" ", s.decode('ascii', errors='ignore').strip())
# 2. Locate known Peach data structures
sections = [b'CBoatParamSettingsData', b'CBoatSensorVersions', b'CLoggerEventLog']
section_offsets = {}
print("\n[+] Locating Header Blocks:")
for section in sections:
idx = raw_data.find(section)
if idx != -1:
print(f" Found {section.decode('ascii')} at offset: {hex(idx)}")
section_offsets[section.decode('ascii')] = idx
else:
print(f" {section.decode('ascii')} not found.")
# 3. Hunting for the Telemetry Payload
# The actual numerical data (force curves, angles) usually follows the headers.
# We can search for the end of the metadata to find where the binary frames begin.
# As an example, if the payload starts at byte 2048, we slice the array:
# *Note: You will need to adjust `payload_start` by inspecting the hex dump
# right after the CLoggerEventLog or similar final header.
payload_start = 2048 # Placeholder offset
binary_payload = raw_data[payload_start:]
# 4. Decoding the Binary Data (Hypothetical Frame Structure)
# In an Eight, a single "frame" (sample) might look like this:
# - Timestamp (4 bytes)
# - Boat Acceleration (4 bytes)
# - Boat Velocity (4 bytes)
# - 8 x Oar Angles (8 * 4 bytes = 32 bytes)
# - 8 x Gate Forces (8 * 4 bytes = 32 bytes)
# Total = 76 bytes per frame (This is an educated guess to help you start testing)
estimated_frame_size = 76
num_frames = len(binary_payload) // estimated_frame_size
print(f"\n[+] Analyzing Binary Payload:")
print(f" Estimated payload size: {len(binary_payload)} bytes")
print(f" Attempting to unpack as {estimated_frame_size}-byte frames ({num_frames} frames)")
if num_frames > 0:
# Example: Using numpy to reshape the binary data into a readable matrix
# 'f' denotes 32-bit floats. Adjust the format string based on whether Peach uses ints or floats.
try:
# We truncate any trailing bytes that don't fit into a perfect frame
valid_payload = binary_payload[:num_frames * estimated_frame_size]
# Format: 'f' for float32. 76 bytes / 4 bytes per float = 19 floats per frame
data_matrix = np.frombuffer(valid_payload, dtype=np.float32).reshape((num_frames, -1))
print(f" Successfully shaped data into {data_matrix.shape[0]} rows and {data_matrix.shape[1]} columns.")
print(" Row 1 Sample:", data_matrix[0])
except Exception as e:
print(" Failed to parse binary matrix. You may need to adjust the frame size or data types (e.g., mix of int32 and float32). Error:", e)
print("\n[+] Analysis Complete. Use the above insights to refine your parsing strategy and extract meaningful telemetry data.")
if __name__ == "__main__":
args = arg_parser()
# Point this to one of your uploaded files
input_dir = "input_data"
file = "row005409-001049D"
analyze_peach_file(f"{input_dir}/{file}.peach-data")