first commit

This commit is contained in:
lihansani
2026-07-13 15:37:05 +08:00
commit 8b11aa2efc
299 changed files with 206339 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,37 @@
e:\vdes\上位机\controller2.0.0\release\democan.pch
e:\vdes\上位机\controller2.0.0\release\vc142.pdb
e:\vdes\上位机\controller2.0.0\release\stdafx.obj
e:\vdes\上位机\controller2.0.0\release\serialport.obj
e:\vdes\上位机\controller2.0.0\release\demovdedlg.obj
e:\vdes\上位机\controller2.0.0\release\demostatedlg.obj
e:\vdes\上位机\controller2.0.0\release\democandlg.obj
e:\vdes\上位机\controller2.0.0\release\democan.obj
e:\vdes\上位机\controller2.0.0\release\coloredlistctrl.obj
e:\vdes\上位机\controller2.0.0\release\cdspprogramdata.obj
e:\vdes\上位机\controller2.0.0\release\cdemotestdlg.obj
e:\vdes\上位机\controller2.0.0\release\democan.exe
e:\vdes\上位机\controller2.0.0\release\usbcan_demo.pdb
e:\vdes\上位机\controller2.0.0\release\democan.res
e:\vdes\上位机\controller2.0.1\release\cdemotestdlg.obj
e:\vdes\上位机\controller2.0.1\release\cdspprogramdata.obj
e:\vdes\上位机\controller2.0.1\release\coloredlistctrl.obj
e:\vdes\上位机\controller2.0.1\release\democan.obj
e:\vdes\上位机\controller2.0.1\release\democandlg.obj
e:\vdes\上位机\controller2.0.1\release\demostatedlg.obj
e:\vdes\上位机\controller2.0.1\release\demovdedlg.obj
e:\vdes\上位机\controller2.0.1\release\serialport.obj
e:\vdes\上位机\controller2.0.1\release\stdafx.obj
e:\vdes\上位机\controller2.0.1\release\democan.res
e:\vdes\上位机\controller2.0.1\release\democan.pch
e:\vdes\上位机\controller2.0.1\release\usbcan_demo.pdb
e:\vdes\上位机\controller2.0.1\release\vc142.pdb
e:\vdes\上位机\controller2.0.1\release\democan.exe
e:\vdes\上位机\controller2.0.1\release\democan.tlog\cl.command.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\cl.read.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\cl.write.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\link.command.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\link.read.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\link.write.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\rc.command.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\rc.read.1.tlog
e:\vdes\上位机\controller2.0.1\release\democan.tlog\rc.write.1.tlog

Binary file not shown.

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>E:\VDES\上位机\controller2.0.1\Release\DemoCAN.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>

View File

@@ -0,0 +1,49 @@
StdAfx.cpp
_WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h)
CDemoTestDlg.cpp
E:\VDES\上位机\controller2.0.1\CDemoTestDlg.cpp(113,10): warning C4101: “exitcode”: 未引用的局部变量
E:\VDES\上位机\controller2.0.1\CDemoTestDlg.cpp(516,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\CDemoTestDlg.cpp(1058,7): warning C4101: “fileExist”: 未引用的局部变量
CDspProgramData.cpp
ColoredListCtrl.cpp
DemoCAN.cpp
DemoCANDlg.cpp
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(507,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(512,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(534,25): warning C4018: “<”: 有符号/无符号不匹配
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(937,20): warning C4244: “初始化”: 从“ULONGLONG”转换到“UINT”可能丢失数据
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(1020,9): warning C4996: 'localtime': This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(1830,10): warning C4996: 'WSAAsyncSelect': Use WSAEventSelect() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(1841,29): warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(1887,16): warning C4244: “初始化”: 从“ULONGLONG”转换到“int”可能丢失数据
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(1923,16): warning C4244: “初始化”: 从“ULONGLONG”转换到“int”可能丢失数据
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(2668,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(3863,19): warning C4996: '_tcstok': This function or variable may be unsafe. Consider using _tcstok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
E:\VDES\上位机\controller2.0.1\DemoCANDlg.cpp(3864,19): warning C4996: '_tcstok': This function or variable may be unsafe. Consider using _tcstok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
DemoStateDlg.cpp
DemoVDEDlg.cpp
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(563,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(564,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(565,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(566,15): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(701,25): warning C4244: “=”: 从“ULONGLONG”转换到“UINT32”可能丢失数据
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(726,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(727,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(861,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(862,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(930,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(931,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1005,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1006,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1081,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1082,13): warning C4309: “=”: 截断常量值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1176,24): warning C4244: “=”: 从“ULONGLONG”转换到“UINT32”可能丢失数据
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1202,16): warning C4018: “<”: 有符号/无符号不匹配
SerialPort.cpp
正在生成代码...
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(905): warning C4715: “DemoVDEDlg::Lvds_Send_LinkID”: 不是所有的控件路径都返回值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(980): warning C4715: “DemoVDEDlg::Lvds_Send_Buffer_Config”: 不是所有的控件路径都返回值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1057): warning C4715: “DemoVDEDlg::Lvds_Send_Satellite_Param”: 不是所有的控件路径都返回值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1124): warning C4715: “DemoVDEDlg::Lvds_Send_Message_ID”: 不是所有的控件路径都返回值
E:\VDES\上位机\controller2.0.1\DemoVDEDlg.cpp(1480): warning C4715: “DemoVDEDlg::Arguments_Auto_Configuration”: 不是所有的控件路径都返回值
DemoCAN.vcxproj -> E:\VDES\上位机\controller2.0.1\Release\DemoCAN.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,2 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.29.30133:VCServicingVersionMFC=14.29.30136:TargetPlatformVersion=10.0.19041.0:
Release|Win32|E:\VDES\上位机\controller2.0.1\|

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,13 @@
E:\vdes\controller\controller1.2\Release\DemoCAN.exe
E:\vdes\controller\controller1.3-test\Release\DemoCAN.exe
E:\vdes\controller\controller1.3\Release\DemoCAN.exe
E:\vdes\controller\controller1.4\Release\DemoCAN.exe
E:\vdes\controller\controller1.4.1\Release\DemoCAN.exe
E:\vdes\controller\controller1.5.1\Release\DemoCAN.exe
E:\vdes\controller\controller1.5.3\Release\DemoCAN.exe
E:\vdes\controller\controller1.5.6\Release\DemoCAN.exe
E:\vdes\controller\controller1.6.0\Release\DemoCAN.exe
E:\vdes\controller\controller1.6.1\Release\DemoCAN.exe
E:\vdes\controller\controller1.7.0\Release\DemoCAN.exe
E:\VDES\上位机\controller2.0.0\Release\DemoCAN.exe
E:\VDES\上位机\controller2.0.1\Release\DemoCAN.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
with open("TCP_VDES报文消息.bin", "rb") as f:
data = f.read()
print(data.hex())
# 帧起始标志
delimiter = b"####"
# 按标志切分
frames = data.split(delimiter)
# 第一个切分出来的可能是空的(因为文件就是以 #### 开头)
for i, frame in enumerate(frames):
if not frame:
continue
# 打印时把起始标志加回去
ais_packet = delimiter + frame
print(f"Frame {i}:")
print((delimiter + frame).hex())
print("-" * 60)

434
协议资料/vdes-tcp.py Normal file
View File

@@ -0,0 +1,434 @@
import struct
from enum import Enum
from typing import Dict, Any
class VDESMessageType(Enum):
"""VDES报文类型枚举"""
DEBUG_COMMAND = 0
LVDS_DATA = 1
CAN_DATA = 2
AD9361_CONTROL = 3
WAVE_IP_CONTROL = 4
TEST_PARAM_CONTROL = 5
TEST_WAVE_UPLOAD = 6
GPS_DATA = 7
STATUS_MONITOR = 8
VDES_PARAM_CONTROL = 9
VDES_UPLOAD_DATA = 10
VDES_COLLECT_DATA = 11
VDES_DEMOD_DATA = 12
NOTIFICATION = 13
class VDESUploadDataType(Enum):
"""VDES上注数据类型枚举"""
LONG_DATA_PARAM = 0
LONG_DATA_CONTENT = 1
LONG_DATA_END = 2
SHORT_MESSAGE = 3
EMERGENCY_MESSAGE = 4
class VDESTCPParser:
"""VDES TCP协议解析器"""
HEADER_MAGIC = b'####'
MAX_PACKET_SIZE = 32768
def __init__(self):
self._init_parsers()
def _init_parsers(self):
"""初始化各类型报文的解析方法"""
self._parsers = {
VDESMessageType.DEBUG_COMMAND: self._parse_debug_command,
VDESMessageType.LVDS_DATA: self._parse_lvds_data,
VDESMessageType.CAN_DATA: self._parse_can_data,
VDESMessageType.AD9361_CONTROL: self._parse_ad9361_control,
VDESMessageType.WAVE_IP_CONTROL: self._parse_wave_ip_control,
VDESMessageType.TEST_PARAM_CONTROL: self._parse_test_param_control,
VDESMessageType.TEST_WAVE_UPLOAD: self._parse_test_wave_upload,
VDESMessageType.GPS_DATA: self._parse_gps_data,
VDESMessageType.STATUS_MONITOR: self._parse_status_monitor,
VDESMessageType.VDES_PARAM_CONTROL: self._parse_vdes_param_control,
VDESMessageType.VDES_UPLOAD_DATA: self._parse_vdes_upload_data,
VDESMessageType.VDES_COLLECT_DATA: self._parse_vdes_collect_data,
VDESMessageType.VDES_DEMOD_DATA: self._parse_vdes_demod_data,
VDESMessageType.NOTIFICATION: self._parse_notification,
}
def parse_packet(self, data: bytes) -> Dict[str, Any]:
"""
解析TCP报文
:param data: 原始报文数据
:return: 解析后的字典结果
"""
if len(data) < 12:
raise ValueError(f"Packet too short ({len(data)} bytes), minimum 12 bytes required")
# 验证报文头
header = data[:4]
if header != self.HEADER_MAGIC:
raise ValueError(f"Invalid packet header: {header.hex()}")
# 解析报文类型和长度
msg_type, content_len = struct.unpack('>II', data[4:12])
content = data[12:12+content_len]
# 验证内容长度
if len(content) != content_len:
raise ValueError(f"Content length mismatch: expected {content_len}, got {len(content)}")
# 获取报文类型枚举
try:
msg_type_enum = VDESMessageType(msg_type)
except ValueError:
return {
'type': msg_type,
'type_name': f'UNKNOWN_{msg_type}',
'content': content,
'raw': data
}
# 调用对应的解析方法
parser = self._parsers.get(msg_type_enum)
if parser:
return {
'type': msg_type_enum,
'type_name': msg_type_enum.name,
'content': parser(content),
'raw': data
}
else:
return {
'type': msg_type_enum,
'type_name': msg_type_enum.name,
'content': content,
'raw': data
}
def _parse_debug_command(self, content: bytes) -> Dict[str, Any]:
"""解析调试指令报文(类型0)"""
if len(content) < 1:
raise ValueError("Debug command too short")
cmd_type = content[0]
descriptions = {
0: "初始化地检",
1: "测试波形上注完成",
2: "LVDS数据开始上注",
3: "LVDS初始化",
4: "AD9361重新校准",
5: "GPS初始化"
}
return {
'command_type': cmd_type,
'description': descriptions.get(cmd_type, f"未知指令类型: {cmd_type}")
}
def _parse_lvds_data(self, content: bytes) -> Dict[str, Any]:
"""解析LVDS数据报文(类型1)"""
return {
'data': content,
'length': len(content)
}
def _parse_can_data(self, content: bytes) -> Dict[str, Any]:
"""解析CAN数据报文(类型2)"""
return {
'data': content,
'length': len(content)
}
def _parse_ad9361_control(self, content: bytes) -> Dict[str, Any]:
"""解析AD9361参数控制报文(类型3)"""
if len(content) != 13:
raise ValueError("AD9361 control message must be 13 bytes")
tx_lo, tx_rate, tx_atten = struct.unpack('>QIB', content)
return {
'tx_lo_freq': tx_lo,
'tx_sample_rate': tx_rate,
'tx_attenuation': tx_atten
}
def _parse_wave_ip_control(self, content: bytes) -> Dict[str, Any]:
"""解析波形发射IP核控制报文(类型4)"""
if len(content) < 20:
raise ValueError("Wave IP control message too short")
# 解析固定部分
channel, cic_enable, sample_rate, wave_type = struct.unpack('>BBIB', content[:7])
freq_offset, sweep_type, sweep_bw, sweep_speed = struct.unpack('>iBII', content[7:20])
return {
'channel': channel,
'cic_enable': bool(cic_enable),
'sample_rate': sample_rate,
'wave_type': wave_type,
'freq_offset': freq_offset,
'sweep_type': sweep_type,
'sweep_bandwidth': sweep_bw,
'sweep_speed': sweep_speed
}
def _parse_test_param_control(self, content: bytes) -> Dict[str, Any]:
"""解析发送测试参数控制报文(类型5)"""
if len(content) != 9:
raise ValueError("Test param control message must be 9 bytes")
test_type, test_count, test_interval = struct.unpack('>BII', content)
return {
'test_type': test_type,
'test_count': test_count,
'test_interval_ms': test_interval
}
def _parse_test_wave_upload(self, content: bytes) -> Dict[str, Any]:
"""解析发送测试波形上注报文(类型6)"""
return {
'wave_data': content,
'length': len(content)
}
def _parse_gps_data(self, content: bytes) -> Dict[str, Any]:
"""解析GPS解析数据报文(类型7)"""
if len(content) < 36:
raise ValueError("GPS data message too short")
fields = struct.unpack('>QiiihhhBBIBII', content[:36])
return {
'utc_time': fields[0],
'longitude': fields[1],
'latitude': fields[2],
'altitude': fields[3],
'used_satellites': fields[4],
'gps_satellites': fields[5],
'beidou_satellites': fields[6],
'gps_status': fields[7],
'position_mode': fields[8],
'hdop': fields[9],
'speed': fields[10],
'direction': fields[11]
}
def _parse_status_monitor(self, content: bytes) -> Dict[str, Any]:
"""解析地检状态监控报文(类型8)"""
if len(content) < 53:
raise ValueError("Status monitor message too short")
# 解析前38字节
fields = struct.unpack('>BBIIBBBBIIIBIII', content[:38])
result = {
'cpu0_usage': fields[0],
'cpu1_usage': fields[1],
'version': fields[2],
'uptime': fields[3],
'gps_status': fields[4],
'pps_lock_status': fields[5],
'ad9361_status': fields[6],
'ad9361_calibration_factor': fields[7],
'ad9361_tx_lo': fields[8],
'ad9361_tx_rate': fields[9],
'ad9361_tx_atten': fields[10],
'ad9361_rx_lo': fields[11],
'ad9361_rx_rate': fields[12],
'ad9361_rx_gain': fields[13],
'vdes_enable': fields[14],
}
# 解析剩余部分
pos = 38
more_fields = struct.unpack('>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB', content[pos:pos+15])
result.update({
'vdes_filter_enable': more_fields[0],
'rac_limit_enable': more_fields[1],
'vdes_agc_enable': more_fields[2],
'sat_delay_comp_enable': more_fields[3],
'upper_sat_id': more_fields[4],
'upper_sat_cqi': more_fields[5],
'upper_sat_amp': more_fields[6],
'lower_sat_id': more_fields[7],
'lower_sat_cqi': more_fields[8],
'lower_sat_power': more_fields[9],
'current_sat_id': more_fields[10],
'current_slot': more_fields[11],
'current_subframe': more_fields[12],
'vdes_tx_link_id': more_fields[13],
'vdes_tx_channel': more_fields[14],
'vdes_tx_freq': more_fields[15],
'vdes_buffer1_status': more_fields[16],
'vdes_buffer2_status': more_fields[17],
'vdes_demod1_enable': more_fields[18],
'vdes_demod1_link_id': more_fields[19],
'vdes_demod1_channel': more_fields[20],
'vdes_demod1_freq': more_fields[21],
'vdes_demod2_enable': more_fields[22],
'vdes_demod2_link_id': more_fields[23],
'vdes_demod2_channel': more_fields[24],
'vdes_demod2_freq': more_fields[25],
'vdes_demod3_enable': more_fields[26],
'vdes_demod3_link_id': more_fields[27],
'vdes_demod3_channel': more_fields[28],
'vdes_demod3_freq': more_fields[29],
'vdes_demod4_enable': more_fields[30],
'vdes_demod4_link_id': more_fields[31],
'vdes_demod4_channel': more_fields[32],
'vdes_demod4_freq': more_fields[33],
'ais_demod1_enable': more_fields[34],
'ais_demod1_freq': more_fields[35],
'ais_demod2_enable': more_fields[36],
'ais_demod2_freq': more_fields[37],
})
return result
def _parse_vdes_param_control(self, content: bytes) -> Dict[str, Any]:
"""解析VDES协议参数控制报文(类型9)"""
if len(content) < 18:
raise ValueError("VDES param control message too short")
fields = struct.unpack('>BBBBIBBBiBIBBBiB', content[:18])
return {
'vdes_enable': fields[0],
'filter_enable': fields[1],
'rac_limit_enable': fields[2],
'agc_enable': fields[3],
'sat_delay_comp_enable': fields[4],
'mmsi': fields[5],
'default_tx_link_id': fields[6],
'default_tx_channel': fields[7],
'default_tx_freq': fields[8],
'tx_delay': fields[9],
'tx_power_atten': fields[10],
'demod1_link_id': fields[11],
'demod1_channel': fields[12],
'demod1_freq': fields[13],
'rx_delay': fields[14],
'rx_gain': fields[15],
'clear_buffer1': fields[16],
'clear_buffer2': fields[17],
}
def _parse_vdes_upload_data(self, content: bytes) -> Dict[str, Any]:
"""解析VDES上注数据报文(类型10)"""
if len(content) < 1:
raise ValueError("VDES upload data message too short")
data_type = content[0]
try:
data_type_enum = VDESUploadDataType(data_type)
except ValueError:
data_type_enum = None
result = {'data_type': data_type}
if data_type_enum == VDESUploadDataType.LONG_DATA_PARAM:
if len(content) < 6:
raise ValueError("Long data param message too short")
target_mmsi, priority = struct.unpack('>IB', content[1:6])
result.update({
'target_mmsi': target_mmsi,
'priority': priority
})
elif data_type_enum == VDESUploadDataType.LONG_DATA_CONTENT:
result['data'] = content[1:]
elif data_type_enum == VDESUploadDataType.SHORT_MESSAGE:
if len(content) < 6:
raise ValueError("Short message too short")
msg_type, target_mmsi = struct.unpack('>BI', content[1:6])
msg_data = content[6:]
result.update({
'message_type': msg_type,
'target_mmsi': target_mmsi,
'message_data': msg_data
})
return result
def _parse_vdes_collect_data(self, content: bytes) -> Dict[str, Any]:
"""解析VDES采集波形报文(类型11)"""
if len(content) != 3584:
raise ValueError("VDES collect data must be 3584 bytes")
return {
'wave_data': content,
'length': len(content)
}
def _parse_vdes_demod_data(self, content: bytes) -> Dict[str, Any]:
"""解析VDES/AIS解调数据报文(类型12)"""
if len(content) < 8:
raise ValueError("VDES demod data message too short")
msg_type, sat_id, demod_id, slot, delay, snr = struct.unpack('>BBBHHh', content[:8])
demod_data = content[8:]
return {
'message_type': msg_type,
'satellite_id': sat_id,
'demodulator_id': demod_id,
'slot': slot,
'delay_us': delay,
'snr_db': snr / 256, # 转换为浮点数
'demod_data': demod_data
}
def _parse_notification(self, content: bytes) -> Dict[str, Any]:
"""解析消息通知报文(类型13)"""
if len(content) < 1:
raise ValueError("Notification message too short")
notif_type = content[0]
descriptions = {
0: "VDES协议开始执行",
1: "VDES协议停止执行",
2: "VDES功能初始化",
3: "VDES开始采集波形",
4: "VDES正在采集波形",
5: "VDES停止采集波形",
6: "VDES收到上行数据",
7: "VDES与卫星建立会话成功",
8: "VDES与卫星结束会话",
9: "VDES发送上行测试波形",
10: "VDES上行测试完毕",
11: "VDES发送上行数据",
12: "VDES解调数据"
}
return {
'notification_type': notif_type,
'description': descriptions.get(notif_type, f"未知通知类型: {notif_type}"),
'additional_data': content[1:] if len(content) > 1 else None
}
# 使用示例
if __name__ == "__main__":
parser = VDESTCPParser()
# 示例1: 解析调试指令报文
debug_cmd = b'####\x00\x00\x00\x00\x00\x00\x00\x01\x02'
try:
result = parser.parse_packet(debug_cmd)
print("调试指令报文解析结果:")
print(f"类型: {result['type_name']}")
print(f"内容: {result['content']}")
except ValueError as e:
print(f"解析错误: {e}")
# 示例2: 解析GPS数据报文
gps_data = b'####\x00\x00\x00\x07\x00\x00\x00\x24' + \
b'\x00\x00\x00\x00\x00\x00\x00\x01' + \
b'\x00\x00\x00\x02\x00\x00\x00\x03' + \
b'\x00\x00\x00\x04\x00\x05\x00\x06' + \
b'\x00\x07\x01\x02\x00\x00\x00\x08' + \
b'\x00\x00\x00\x09\x00\x00\x00\x0A'
try:
result = parser.parse_packet(gps_data)
print("\nGPS数据报文解析结果:")
print(f"类型: {result['type_name']}")
print(f"内容: {result['content']}")
except ValueError as e:
print(f"解析错误: {e}")

View File

@@ -0,0 +1,353 @@
import socket
import threading
import queue
import random
import struct
import time
import math
from datetime import datetime
# 全局配置
HOST = 'localhost'
PORT = 10
BUFFER_SIZE = 32768
FRAME_HEADER = b'####'
# 长江入海口位置 (中心点)
YANGTZE_ESTUARY_LAT = 31.23
YANGTZE_ESTUARY_LON = 121.47
RANGE_NM = 5 # 5海里范围
# 预生成10艘船的MMSI
SHIP_MMSIS = [random.randint(200000000, 299999999) for _ in range(10)]
# 报文类型定义
MSG_TYPE_DEBUG = 0
MSG_TYPE_LVDS = 1
MSG_TYPE_CAN = 2
MSG_TYPE_AD9361 = 3
MSG_TYPE_WAVE_CTRL = 4
MSG_TYPE_TEST_PARAM = 5
MSG_TYPE_TEST_WAVE = 6
MSG_TYPE_GPS = 7
MSG_TYPE_STATUS = 8
MSG_TYPE_VDES_CTRL = 9
MSG_TYPE_VDES_UPLOAD = 10
MSG_TYPE_COLLECT = 11
MSG_TYPE_DEMOD = 12
MSG_TYPE_NOTIFY = 13
# 解调器类型
DEMOD_VDES = 0 # VDES解调器 (0-3)
DEMOD_AIS = 4 # AIS解调器 (4-5)
# 通信状态定义 (Annex 2 Table 18)
COMM_STATES = [
{"sync_state": 0, "slot_timeout": 0, "sub_message": 0},
{"sync_state": 1, "slot_timeout": 1, "sub_message": 1},
{"sync_state": 2, "slot_timeout": 2, "sub_message": 2},
{"sync_state": 3, "slot_timeout": 3, "sub_message": 3}
]
class VDESTCPServer:
def __init__(self):
self.send_queue = queue.Queue()
self.running = True
self.device_state = {
"cpu0": 50,
"cpu1": 50,
"version": 0x01020304,
"uptime": int(time.time()),
"gps_status": 1,
"pps_lock": 1,
"ad9361_status": 2
}
self.gps_params = self.generate_gps_data()
def start(self):
# server_thread = threading.Thread(target=self.run_server)
# server_thread.daemon = True
# server_thread.start()
# send_thread = threading.Thread(target=self.send_data_thread)
# send_thread.daemon = True
# send_thread.start()
# server_thread.join()
# send_thread.join()
print(11111111111)
print(self.build_gps_message())
def run_server(self):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
print(f"VDES TCP Server listening on {HOST}:{PORT}")
while self.running:
conn, addr = s.accept()
print(f"Connected by {addr}")
client_thread = threading.Thread(target=self.handle_client, args=(conn,))
client_thread.daemon = True
client_thread.start()
def handle_client(self, conn):
with conn:
while self.running:
try:
data = conn.recv(BUFFER_SIZE)
if not data:
break
# 解析报文
if len(data) < 12:
print("Invalid packet size")
continue
header = data[:4]
if header != FRAME_HEADER:
print("Invalid frame header")
continue
msg_type = struct.unpack('>I', data[4:8])[0]
msg_len = struct.unpack('>I', data[8:12])[0]
msg_content = data[12:12+msg_len] if msg_len > 0 else b''
print(f"Received message type: {msg_type}, length: {msg_len}")
# 处理报文并准备响应
response = self.process_message(msg_type, msg_content)
if response:
self.send_queue.put(response)
except Exception as e:
print(f"Error handling client: {e}")
break
def process_message(self, msg_type, content):
"""处理接收到的报文并返回响应"""
response = None
if msg_type == MSG_TYPE_DEBUG:
# 调试指令报文
if len(content) >= 1:
cmd_type = content[0]
print(f"Received debug command: {cmd_type}")
# 简单响应通知报文
response = self.build_notify_message(0, "Debug command processed")
elif msg_type == MSG_TYPE_AD9361:
# AD9361参数控制
print("Received AD9361 control params")
response = self.build_notify_message(0, "AD9361 params updated")
elif msg_type == MSG_TYPE_TEST_PARAM:
# 发送测试参数控制
if len(content) >= 9:
test_type, test_count, test_interval = struct.unpack('>BII', content[:9])
print(f"Test params: type={test_type}, count={test_count}, interval={test_interval}ms")
response = self.build_notify_message(0, "Test params accepted")
elif msg_type == MSG_TYPE_VDES_CTRL:
# VDES协议参数控制
print("Received VDES control params")
response = self.build_notify_message(0, "VDES params updated")
elif msg_type == MSG_TYPE_VDES_UPLOAD:
# VDES上注数据
if len(content) >= 1:
data_type = content[0]
print(f"VDES upload data type: {data_type}")
response = self.build_notify_message(0, "Data upload accepted")
return response
def send_data_thread(self):
"""发送线程定期发送GPS和解调数据报文"""
while self.running:
try:
# 发送GPS数据 (每秒一次)
self.gps_params = self.generate_gps_data()
gps_msg = self.build_gps_message()
self.send_queue.put(gps_msg)
# 发送解调数据 (随机间隔)
if random.random() > 0.7:
demod_msg = self.build_demod_message()
self.send_queue.put(demod_msg)
# 发送状态监控数据 (每秒一次)
status_msg = self.build_status_message()
self.send_queue.put(status_msg)
# 发送队列中的响应报文
while not self.send_queue.empty():
msg = self.send_queue.get()
# 在实际服务器中,这里应该发送给所有连接的客户端
# 本示例中仅打印发送信息
print(f"Sending message type: {struct.unpack('>I', msg[4:8])[0]}, "
f"length: {struct.unpack('>I', msg[8:12])[0]}")
time.sleep(1)
except Exception as e:
print(f"Error in send thread: {e}")
def build_packet(self, msg_type, content):
"""构建完整TCP报文"""
header = FRAME_HEADER
type_field = struct.pack('>I', msg_type)
length_field = struct.pack('>I', len(content))
return header + type_field + length_field + content
def build_gps_message(self):
"""构建GPS解析数据报文 (类型7)"""
content = struct.pack('>QiiihhhBBBBBB',
self.gps_params["utc_time"],
self.gps_params["longitude"],
self.gps_params["latitude"],
self.gps_params["altitude"],
self.gps_params["used_sats"],
self.gps_params["gps_sats"],
self.gps_params["beidou_sats"],
self.gps_params["gps_status"],
self.gps_params["fix_mode"],
self.gps_params["hdop"],
self.gps_params["speed"],
self.gps_params["course"])
return self.build_packet(MSG_TYPE_GPS, content)
def build_demod_message(self):
"""构建VDES解调数据报文 (类型12)"""
demod_id = random.randint(0, 5)
comm_state = random.choice(COMM_STATES)
if demod_id <= DEMOD_VDES + 3: # VDES解调器 (0-3)
# 根据M.2092-1 Annex5 3.10生成消息
msg_data = self.generate_vdes_message()
else: # AIS解调器 (4-5)
# 根据M.1371-5 Annex8 3.1生成Message1
msg_data = self.generate_ais_message1()
# 构建通信状态字段
comm_state_field = struct.pack('>BBH',
(comm_state["sync_state"] << 6) | (comm_state["slot_timeout"] << 3),
comm_state["sub_message"] >> 8,
comm_state["sub_message"] & 0xFF)
# 构建完整报文
content = struct.pack('>BBHH', 12, demod_id, random.randint(0, 65535), random.randint(0, 65535))
content += struct.pack('>H', random.randint(-12800, 12700)) # 信噪比
content += comm_state_field
content += msg_data
return self.build_packet(MSG_TYPE_DEMOD, content)
def build_status_message(self):
"""构建地检状态监控报文 (类型8)"""
# 更新设备状态
self.device_state["cpu0"] = random.randint(40, 60)
self.device_state["cpu1"] = random.randint(40, 60)
self.device_state["uptime"] = int(time.time())
# 构建报文内容 (简化版)
content = struct.pack('>BBIIBBBB',
self.device_state["cpu0"],
self.device_state["cpu1"],
self.device_state["version"],
self.device_state["uptime"],
self.device_state["gps_status"],
self.device_state["pps_lock"],
self.device_state["ad9361_status"],
0) # 校准因子占位
return self.build_packet(MSG_TYPE_STATUS, content)
def build_notify_message(self, msg_type, text):
"""构建消息通知报文 (类型13)"""
text_bytes = text.encode('utf-8')
content = struct.pack('>B', msg_type) + text_bytes
return self.build_packet(MSG_TYPE_NOTIFY, content)
def generate_gps_data(self):
"""生成GPS数据 (长江入海口5海里范围内)"""
# 在中心点附近5海里范围内生成随机位置
lat, lon = self.generate_random_position()
return {
"utc_time": int(time.time()),
"longitude": int(lon * 10000000),
"latitude": int(lat * 10000000),
"altitude": random.randint(-50, 100),
"used_sats": random.randint(5, 12),
"gps_sats": random.randint(3, 8),
"beidou_sats": random.randint(3, 8),
"gps_status": random.randint(0, 4),
"fix_mode": random.randint(1, 3),
"hdop": random.randint(10, 100),
"speed": random.randint(0, 2000), # 0.01节单位
"course": random.randint(0, 35900) # 0.01度单位
}
def generate_random_position(self):
"""在长江入海口5海里范围内生成随机位置"""
# 1海里 ≈ 0.0166667度 (赤道附近)
offset_lat = (random.random() - 0.5) * RANGE_NM * 0.0166667
offset_lon = (random.random() - 0.5) * RANGE_NM * 0.0166667
lat = YANGTZE_ESTUARY_LAT + offset_lat
lon = YANGTZE_ESTUARY_LON + offset_lon
return lat, lon
def generate_vdes_message(self):
"""生成VDES消息 (M.2092-1 Annex5 3.10)"""
# 随机选择一种消息类型 (简化实现)
msg_types = [0, 1, 2, 3, 4, 5]
msg_type = random.choice(msg_types)
# 构建基本消息结构
msg = struct.pack('>B', msg_type)
# 添加随机内容
if msg_type == 0: # Paging
msg += struct.pack('>I', random.randint(100000000, 999999999))
elif msg_type == 1: # Resource request
msg += struct.pack('>IB', random.randint(100000000, 999999999), random.randint(0, 255))
return msg
def generate_ais_message1(self):
"""生成AIS Message1位置报告 (M.1371-5 Annex8 3.1)"""
# 随机位置
lat, lon = self.generate_random_position()
# 转换为AIS格式
lat_ais = int((lat + 90) * 60000)
lon_ais = int((lon + 180) * 60000)
# 随机选择一艘船
mmsi = random.choice(SHIP_MMSIS)
# 随机通信状态
comm_state = random.choice(COMM_STATES)
comm_state_field = (
(comm_state["sync_state"] << 17) |
(comm_state["slot_timeout"] << 14) |
comm_state["sub_message"]
)
# 构建Message1 (168位/21字节)
msg = struct.pack('>I', (1 << 26) | (random.randint(0, 3) << 24) | (mmsi >> 6))
msg += struct.pack('>I', ((mmsi & 0x3F) << 26) | (random.randint(0, 15) << 22))
msg += struct.pack('>I', (random.randint(0, 255) << 24) | (random.randint(0, 1023) << 14))
msg += struct.pack('>I', (random.randint(0, 1) << 31) | (lon_ais & 0xFFFFFFF))
msg += struct.pack('>I', (lat_ais << 4) | (random.randint(0, 4095) >> 8))
msg += struct.pack('>I', ((random.randint(0, 4095) & 0xFF) << 24) | (random.randint(0, 3599) << 12))
msg += struct.pack('>I', (random.randint(0, 511) << 23) | (random.randint(0, 63) << 17) | (comm_state_field & 0x1FFFF))
return msg
if __name__ == "__main__":
server = VDESTCPServer()
server.start()

View File

@@ -0,0 +1,252 @@
import socket
import struct
import random
import time
import threading
from datetime import datetime, timedelta
# 报文类型常量
MSG_DEBUG = 0
MSG_LVDS = 1
MSG_CAN = 2
MSG_AD9361_CTRL = 3
MSG_WAVE_CTRL = 4
MSG_TEST_PARAM_CTRL = 5
MSG_TEST_WAVE_UPLOAD = 6
MSG_GPS = 7
MSG_STATUS_MONITOR = 8
MSG_PROTO_PARAM_CTRL = 9
MSG_DATA_UPLOAD = 10
MSG_DATA_COLLECT = 11
MSG_DEMOD_DATA = 12
MSG_NOTIFICATION = 13
# 解调器编号常量
VDES_DEMOD_RANGE = (0, 3) # VDES解调器编号0-3
AIS_DEMOD_RANGE = (4, 5) # AIS解调器编号4-5
# 长江入海口坐标范围 (31.0°N - 31.5°N, 121.5°E - 122.0°E)
YANGTZE_DELTA_CENTER = (31.23, 121.77) # 上海附近
DELTA_RANGE = 0.05 # ±0.05度 ≈ 5海里
class VDESServer:
def __init__(self, host='localhost', port=10):
self.host = host
self.port = port
self.header = b'####'
self.running = False
self.server_socket = None
self.ship_mmsi = 123456789 # 船舶MMSI
def start(self):
"""启动TCP服务器"""
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(1)
self.running = True
print(f"VDES Server started on {self.host}:{self.port}")
# 接受客户端连接
client_socket, addr = self.server_socket.accept()
print(f"Connected by {addr}")
# 启动接收线程和定时发送线程
recv_thread = threading.Thread(target=self.handle_client, args=(client_socket,))
send_thread = threading.Thread(target=self.send_periodic_messages, args=(client_socket,))
recv_thread.start()
send_thread.start()
recv_thread.join()
send_thread.join()
def stop(self):
"""停止服务器"""
self.running = False
if self.server_socket:
self.server_socket.close()
def build_packet(self, msg_type, content):
"""构建协议报文:帧头(4) + 类型(4) + 长度(4) + 内容(N)"""
length = len(content)
return self.header + struct.pack('>I', msg_type) + struct.pack('>I', length) + content
def parse_packet(self, data):
"""解析接收到的报文"""
if len(data) < 12 or data[:4] != self.header:
return None, None
msg_type = struct.unpack('>I', data[4:8])[0]
length = struct.unpack('>I', data[8:12])[0]
content = data[12:12+length] if len(data) >= 12 + length else None
return msg_type, content
def handle_debug_command(self, content):
"""处理调试指令报文类型0"""
cmd_type = content[0] if content else 0
responses = {
0: "初始化地检",
1: "测试波形上注完成",
2: "LVDS数据开始上注",
3: "CAN初始化",
4: "LVDS初始化",
5: "AD9361重新校准",
6: "GPS初始化"
}
response_msg = responses.get(cmd_type, "未知指令")
print(f"执行调试指令: {response_msg}")
# 返回通知报文确认
return self.build_packet(MSG_NOTIFICATION, struct.pack('B', 0)) # 类型0: VDES协议开始执行
def handle_client(self, client_socket):
"""处理客户端请求"""
while self.running:
try:
data = client_socket.recv(32768)
if not data:
break
msg_type, content = self.parse_packet(data)
if msg_type is None:
continue
# 根据报文类型处理
if msg_type == MSG_DEBUG:
response = self.handle_debug_command(content)
elif msg_type == MSG_AD9361_CTRL:
response = self.build_packet(MSG_NOTIFICATION, struct.pack('B', 7)) # AD9361状态更新
else:
response = self.build_packet(MSG_NOTIFICATION, struct.pack('B', 3)) # 通用确认
client_socket.send(response)
except Exception as e:
print(f"处理错误: {e}")
break
def send_periodic_messages(self, client_socket):
"""定时发送状态监控和GPS报文"""
while self.running:
try:
# 每秒发送GPS数据类型7
gps_data = self.generate_gps_data()
client_socket.send(self.build_packet(MSG_GPS, gps_data))
# 每秒发送状态监控类型8
status_data = bytes([random.randint(0, 100) for _ in range(50)]) # 随机状态数据
client_socket.send(self.build_packet(MSG_STATUS_MONITOR, status_data))
# 每5秒发送解调数据类型12
if int(time.time()) % 5 == 0:
demod_data = self.generate_demod_data()
client_socket.send(self.build_packet(MSG_DEMOD_DATA, demod_data))
time.sleep(1)
except Exception as e:
print(f"发送错误: {e}")
break
def generate_gps_data(self):
"""生成长江入海口附近的GPS数据"""
# 在长江入海口附近随机生成位置
lat = YANGTZE_DELTA_CENTER[0] + random.uniform(-DELTA_RANGE, DELTA_RANGE)
lon = YANGTZE_DELTA_CENTER[1] + random.uniform(-DELTA_RANGE, DELTA_RANGE)
# 转换为度分格式*10000000
lat_int = int(lat * 10000000)
lon_int = int(lon * 10000000)
# 其他GPS数据字段
utc_time = int((datetime.utcnow() - datetime(1980, 1, 6)).total_seconds())
altitude = random.randint(-10, 50) # 海拔高度(米)
used_satellites = random.randint(5, 12)
gps_satellites = random.randint(4, 8)
beidou_satellites = random.randint(4, 8)
gps_status = random.randint(1, 4) # GPS状态
pos_mode = random.randint(1, 3) # 定位模式
hdop = random.randint(10, 50) # 水平精度因子
speed = random.randint(0, 2000) # 运动速度 (0.01节)
course = random.randint(0, 35900) # 运动方向 (度*100)
# 打包GPS数据
return struct.pack('>Q', utc_time) + \
struct.pack('>i', lon_int) + \
struct.pack('>i', lat_int) + \
struct.pack('>i', altitude) + \
struct.pack('>H', used_satellites) + \
struct.pack('>H', gps_satellites) + \
struct.pack('>H', beidou_satellites) + \
struct.pack('B', gps_status) + \
struct.pack('B', pos_mode) + \
struct.pack('>I', hdop) + \
struct.pack('>I', speed) + \
struct.pack('>I', course)
def generate_demod_data(self):
"""生成解调数据报文类型12"""
demodulator_id = random.randint(0, 5)
msg_type = 12 # 固定值12
satellite_id = random.randint(1, 255)
demod_data = struct.pack('B', msg_type) + struct.pack('B', satellite_id) + struct.pack('B', demodulator_id)
# 根据解调器编号生成数据
if VDES_DEMOD_RANGE[0] <= demodulator_id <= VDES_DEMOD_RANGE[1]:
# VDES解调器 (0-3): 使用M.2092-1 Annex5格式
msg_id = random.choice([10, 11, 12, 20, 21])
content = struct.pack('B', msg_id) + os.urandom(20) # 随机生成20字节数据
else:
# AIS解调器 (4-5): 使用M.1371-5 Annex8 Message1格式
content = self.generate_ais_message1()
return demod_data + content
def generate_ais_message1(self):
"""生成AIS Message 1位置报告"""
# 在长江入海口附近随机生成位置
lat = YANGTZE_DELTA_CENTER[0] + random.uniform(-DELTA_RANGE, DELTA_RANGE)
lon = YANGTZE_DELTA_CENTER[1] + random.uniform(-DELTA_RANGE, DELTA_RANGE)
# 转换为1/10000分钟格式
lat_min = int(lat * 60 * 10000)
lon_min = int(lon * 60 * 10000)
# 其他AIS字段
message_id = 1
repeat_indicator = 0
navigational_status = random.randint(0, 15) # 航行状态
rate_of_turn = random.randint(-128, 127) # 转向率
speed_over_ground = random.randint(0, 1022) # 对地航速 (0.1节)
position_accuracy = 1 # 高精度
course_over_ground = random.randint(0, 3599) # 对地航向 (0.1度)
true_heading = random.randint(0, 359) # 真航向
timestamp = random.randint(0, 59) # UTC秒
maneuver_indicator = random.randint(0, 1) # 操纵指示器
spare = 0
raim_flag = 0 # RAIM标志
# 打包AIS Message 1
return struct.pack('>B', message_id) + \
struct.pack('>B', (repeat_indicator << 6) | (navigational_status << 2) | (rate_of_turn >> 6)) + \
struct.pack('>B', (rate_of_turn & 0x3F) << 2) | (speed_over_ground >> 8) + \
struct.pack('>B', speed_over_ground & 0xFF) + \
struct.pack('>B', (position_accuracy << 7) | (lon_min >> 25)) + \
struct.pack('>B', (lon_min >> 17) & 0xFF) + \
struct.pack('>B', (lon_min >> 9) & 0xFF) + \
struct.pack('>B', (lon_min >> 1) & 0xFF) + \
struct.pack('>B', ((lon_min & 0x1) << 7) | (lat_min >> 20)) + \
struct.pack('>B', (lat_min >> 12) & 0xFF) + \
struct.pack('>B', (lat_min >> 4) & 0xFF) + \
struct.pack('>B', ((lat_min & 0xF) << 4) | (course_over_ground >> 8)) + \
struct.pack('>B', course_over_ground & 0xFF) + \
struct.pack('>H', true_heading) + \
struct.pack('>B', timestamp) + \
struct.pack('>B', (maneuver_indicator << 2) | spare) + \
struct.pack('>B', raim_flag)
if __name__ == "__main__":
server = VDESServer()
try:
server.start()
except PermissionError:
print("错误需要管理员权限绑定到端口10")
except KeyboardInterrupt:
server.stop()

Binary file not shown.

BIN
协议资料/上位机.zip Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 MiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1 @@
ais在1371-5第三章节109页封装后放在tcp中的表16的解调数据字段。只需要模拟gps和ais vdes在2092-1文件的126页