yincheng.zhong
2 天以前 567085ead3f6adaabd884f16ab4b17c62e8f0403
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import requests
import struct
 
url = "http://39.99.43.227:8866/api/file/download/21b09df9-9232-4e38-a5cc-19458d324019_data.bin"
 
print(f"Downloading from: {url}")
print("-" * 60)
 
try:
    response = requests.get(url, timeout=10)
    
    print(f"Status Code: {response.status_code}")
    print(f"Content-Type: {response.headers.get('Content-Type', 'N/A')}")
    print(f"Content-Length: {response.headers.get('Content-Length', 'N/A')}")
    print(f"Content-Disposition: {response.headers.get('Content-Disposition', 'N/A')}")
    print("-" * 60)
    
    if response.status_code == 200:
        data = response.content
        print(f"Downloaded {len(data)} bytes")
        print("-" * 60)
        
        # 首先查看原始字节
        print(f"First 40 bytes (hex): {data[0:40].hex()}")
        print(f"First 4 bytes as bytes: {[hex(b) for b in data[0:4]]}")
        print("-" * 60)
        
        if len(data) >= 40:
            # 解析头部 (MowerPathHeader_t) - 小端字节序
            # Offset 0-11: 基础信息
            sof = struct.unpack('>H', data[0:2])[0]  # 大端读取SOF
            file_type = data[2]
            version = data[3]
            path_id = struct.unpack('<I', data[4:8])[0]
            timestamp = struct.unpack('<I', data[8:12])[0]
            
            # Offset 12-35: 保留与高精度数据
            reserved = struct.unpack('<I', data[12:16])[0]
            origin_lon = struct.unpack('<d', data[16:24])[0]
            origin_lat = struct.unpack('<d', data[24:32])[0]
            origin_alt = struct.unpack('<f', data[32:36])[0]
            
            # Offset 36-39: 数量信息
            boundary_count = struct.unpack('<H', data[36:38])[0]
            path_count = struct.unpack('<H', data[38:40])[0]
            
            print("Header parsed:")
            print(f"  SOF: 0x{sof:04X} (expected 0x55AA)")
            print(f"  Type: 0x{file_type:02X} (expected 0x3C)")
            print(f"  Version: 0x{version:02X} (expected 0x10)")
            print(f"  Path ID: {path_id}")
            print(f"  Timestamp: {timestamp}")
            print(f"  Reserved: {reserved}")
            print(f"  Origin: Lat={origin_lat:.8f}, Lon={origin_lon:.8f}, Alt={origin_alt:.2f}")
            print(f"  Boundary points: {boundary_count}")
            print(f"  Path points: {path_count}")
            print("-" * 60)
            
            # 验证格式
            if sof == 0x55AA and file_type == 0x3C and version == 0x10:
                print("✓ Header format is VALID")
                
                # 计算预期数据大小
                expected_size = 40 + (boundary_count + path_count) * 8 + 4
                print(f"Expected total size: {expected_size} bytes (header + points + CRC32)")
                print(f"Actual size: {len(data)} bytes")
                
                if len(data) == expected_size:
                    print("✓ File size matches expected")
                else:
                    print(f"✗ Size mismatch: {len(data) - expected_size:+d} bytes")
                
                print("-" * 60)
                    
                # CRC32验证(测试多种CRC配置)
                import binascii
                import zlib
                
                # 数据部分(不包括最后4字节CRC)
                data_only = data[:-4]
                crc32_stored = struct.unpack('<I', data[-4:])[0]
                
                print(f"CRC32 Verification:")
                print(f"  Stored in file (last 4 bytes): 0x{crc32_stored:08X}")
                print(f"  Data size for CRC: {len(data_only)} bytes")
                print()
                
                # 测试不同的CRC32算法
                # 1. binascii.crc32 (初始值0, 输出直接使用)
                crc1 = binascii.crc32(data_only, 0) & 0xFFFFFFFF
                print(f"  1. binascii.crc32(init=0): 0x{crc1:08X} {'✓ MATCH!' if crc1 == crc32_stored else ''}")
                
                # 2. zlib.crc32 (初始值0)
                crc2 = zlib.crc32(data_only, 0) & 0xFFFFFFFF  
                print(f"  2. zlib.crc32(init=0):     0x{crc2:08X} {'✓ MATCH!' if crc2 == crc32_stored else ''}")
                
                # 3. binascii.crc32 取反(模拟最终XOR)
                crc3 = ~binascii.crc32(data_only, 0) & 0xFFFFFFFF
                print(f"  3. ~binascii.crc32(init=0): 0x{crc3:08X} {'✓ MATCH!' if crc3 == crc32_stored else ''}")
                
                # 4. STM32默认:初始值0xFFFFFFFF,无最终XOR
                crc4 = binascii.crc32(data_only, 0xFFFFFFFF) & 0xFFFFFFFF
                print(f"  4. binascii.crc32(init=0xFFFFFFFF): 0x{crc4:08X} {'✓ MATCH!' if crc4 == crc32_stored else ''}")
                
                # 5. STM32默认+最终XOR
                crc5 = ~binascii.crc32(data_only, 0xFFFFFFFF) & 0xFFFFFFFF
                print(f"  5. ~binascii.crc32(init=0xFFFFFFFF): 0x{crc5:08X} {'✓ MATCH!' if crc5 == crc32_stored else ''}")
            else:
                print("✗ Header format is INVALID")
                print(f"First 40 bytes (hex): {data[0:40].hex()}")
        else:
            print(f"✗ File too small (only {len(data)} bytes)")
            print(f"Content (hex): {data.hex()}")
    else:
        print(f"✗ HTTP Error: {response.status_code}")
        print(f"Response body: {response.text[:500]}")
        
except requests.exceptions.RequestException as e:
    print(f"✗ Request failed: {e}")