Files
VDES_Backend/报文模拟解析/develop/receive.py
2026-07-13 15:37:05 +08:00

134 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import socket
import struct
def get_tcp_data(packet_data):
#判断帧头是否符合卓研
if packet_data[:4].decode('ascii') == '####':
print("开始解析报文帧")
packet_type = struct.unpack('>I', packet_data[4:8])[0] #获取报文类型 7为gps 12为ais
packet_lenth = struct.unpack('>I', packet_data[8:12])[0]
packet_content = packet_data[12:]
if packet_type == 7:
print(f"GPS内容长度: {packet_lenth} 字节")
data = get_gps_data(packet_content)
print(data)
elif packet_type == 12:
print(f"AIS内容长度: {packet_lenth} 字节")
data = get_ais_data(packet_content)
print(data)
def get_gps_data(packet_content):
fields = struct.unpack('>QiiiHHHBBIII', packet_content)
res = {}
res['utc_time'] = fields[0] # UTC时间 (8字节)
res['longitude'] = fields[1]/10000000 # 经度 (4字节东经120.5度)
res['latitude'] = fields[2]/10000000 # 纬度 (4字节北纬30.5度)
res['altitude'] = fields[3] # 海拔高度 (4字节50米)
res['used_sats'] = fields[4] # 定位使用的卫星数 (2字节)
res['gps_sats'] = fields[5] # GPS卫星数 (2字节)
res['beidou_sats'] = fields[6] # 北斗卫星数 (2字节)
res['gps_status'] = fields[7] # GPS状态 (1字节单点定位)
res['position_mode'] = fields[8] # 定位模式 (1字节3D定位)
res['hdop'] = fields[9]/10 # 水平精度因子 (4字节25.5米)
res['speed'] = fields[10]/100 # 运动速度 (4字节10.24节)
res['direction'] = fields[11] # 运动方向 (4字节359度)
return res
def get_ais_data(packet_content):
res ={}
demod_packet = packet_content[:9]
demod_data = packet_content[9:]
fields = struct.unpack('>BBBHHH', demod_packet)
res['message_type'] = fields[0]
res['satellite_id'] = fields[1]
res['demodulator_id'] = fields[2]
res['demod_slot'] = fields[3]
res['receive_delay'] = fields[4]
snr_packed = fields[5]
# 解析SNR
snr_int = (snr_packed >> 8) & 0xFF
snr_frac = snr_packed & 0xFF
res['snr'] = snr_int + snr_frac / 100.0
print(demod_data)
res['demod_data'] = get_demod_data(demod_data)
return res
def get_demod_data(bit_string):
# 如果输入是字节类型,先转换为二进制字符串
if isinstance(bit_string, bytes):
bit_string = ''.join(format(byte, '08b') for byte in bit_string)
pos = 0
decoded = {}
decoded['message_id'] = int(bit_string[pos:pos+6], 2) # 消息ID (6 bits)
pos += 6
decoded['repeat_indicator'] = int(bit_string[pos:pos+2], 2) # 转发指示符 (2 bits)
pos += 2
decoded['user_id'] = int(bit_string[pos:pos+30], 2) # 用户ID/MMSI (30 bits)
pos += 30
decoded['navigation_status'] = int(bit_string[pos:pos+4], 2) # 导航状态 (4 bits)
pos += 4
# 旋转速率 (8位有符号整数)
rot_value = int(bit_string[pos:pos+8], 2)
if rot_value > 127:
rot_value -= 256
decoded['rot'] = rot_value
pos += 8
decoded['sog'] = int(bit_string[pos:pos+10], 2) # 地面航速 (10 bits)
pos += 10
decoded['position_accuracy'] = int(bit_string[pos], 2) # 位置准确度 (1 bit)
pos += 1
# 经度 (28位)
longitude_value = int(bit_string[pos:pos+28], 2)
decoded['longitude'] = longitude_value / (60 * 10000) # 转换为度
pos += 28
# 纬度 (27位)
latitude_value = int(bit_string[pos:pos+27], 2)
decoded['latitude'] = latitude_value / (60 * 10000) # 转换为度
pos += 27
decoded['cog'] = int(bit_string[pos:pos+12], 2) # 地面航线 (12 bits)
pos += 12
decoded['true_heading'] = int(bit_string[pos:pos+9], 2) # 实际航向 (9 bits)
pos += 9
decoded['timestamp'] = int(bit_string[pos:pos+6], 2) # 时戳 (6 bits)
pos += 6
decoded['special_maneuver'] = int(bit_string[pos:pos+2], 2) # 特定操纵指示符 (2 bits)
pos += 2
decoded['spare'] = int(bit_string[pos:pos+3], 2) # 备用 (3 bits)
pos += 3
decoded['raim_flag'] = int(bit_string[pos], 2) # RAIM标志 (1 bit)
pos += 1
decoded['comm_state'] = int(bit_string[pos:pos+19], 2) # 通信状态 (19 bits)
return decoded
def receive_data():
"""接收数据"""
host = 'localhost'
port = 8082
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.bind((host, port))
print(f"监听 {host}:{port}...")
while True:
try:
data, addr = s.recvfrom(4096) # 接收缓冲区大小
print(f"\n收到来自 {addr} 的数据:")
print("原始数据(十六进制):", data.hex())
get_tcp_data(data)
except KeyboardInterrupt:
print("\n停止接收")
break
except Exception as e:
print(f"接收错误: {e}")
break
if __name__ == "__main__":
receive_data()