134 lines
5.2 KiB
Python
134 lines
5.2 KiB
Python
|
|
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()
|