Files
VDES_Backend/报文模拟解析/模拟发送.py

350 lines
13 KiB
Python
Raw Normal View History

2026-07-13 15:37:05 +08:00
import struct
import math
def create_tcp_packet(packet_type, content):
"""创建符合VDES TCP协议的报文"""
# 报文帧头 (4字节)
header = b'####'
# 报文类型 (4字节大端)
type_field = struct.pack('>I', packet_type)
# 报文长度 (4字节大端内容长度)
length = len(content)
length_field = struct.pack('>I', length)
# 构建完整报文
packet = header + type_field + length_field + content
return packet
def create_gps_packet():
"""创建GPS解析数据报文(类型7)的内容"""
# 模拟GPS数据 (表11定义)
utc_time = 1680000000 # UTC时间 (8字节)
longitude = 1205000000 # 经度 (4字节东经120.5度)
latitude = 305000000 # 纬度 (4字节北纬30.5度)
altitude = 50 # 海拔高度 (4字节50米)
used_sats = 10 # 定位使用的卫星数 (2字节)
gps_sats = 8 # GPS卫星数 (2字节)
beidou_sats = 7 # 北斗卫星数 (2字节)
gps_status = 1 # GPS状态 (1字节单点定位)
position_mode = 3 # 定位模式 (1字节3D定位)
hdop = 2550 # 水平精度因子 (4字节25.5米)
speed = 1024 # 运动速度 (4字节10.24节)
direction = 359 # 运动方向 (4字节359度)
# 打包为二进制 (大端字节序)
content = struct.pack(
'>QiiiHHHBBIII', # 格式: Q(8),i(4),i(4),i(4),H(2),H(2),H(2),B(1),B(1),I(4),I(4),I(4)
utc_time,
longitude,
latitude,
altitude,
used_sats,
gps_sats,
beidou_sats,
gps_status,
position_mode,
hdop,
speed,
direction
)
return content
def create_ais_info_packet(demod_content):
"""创建解调信息报文(类型12)的内容"""
# 模拟解调信息数据
message_type = 12 # 消息类型 (1字节)
satellite_id = 1 # 卫星ID (1字节)
demodulator_id = 0 # 解调器编号 (1字节)
demod_slot = 1234 # 解调时隙 (2字节)
receive_delay = 5678 # 接收延迟 (2字节单位us)
snr = 25.75 # 信噪比 (2字节dB)
# 处理信噪比 (高8位整数部分低8位小数部分)
snr_int = int(snr)
snr_frac = int((snr - snr_int) * 100) # 转换为0-99的小数部分
snr_packed = (snr_int & 0xFF) << 8 | (snr_frac & 0xFF)
# 打包为二进制 (大端字节序)
content = struct.pack(
'>BBBHHH', # 格式: B(1),B(1),B(1),H(2),H(2),h(2)
message_type,
satellite_id,
demodulator_id,
demod_slot,
receive_delay,
snr_packed
)
return content + demod_content
def encode_demod_fields():
"""编码解调信息字段并打印解码结果"""
# 初始化二进制位列表
bits = []
# 示例数据
message_id = 1 # 消息ID (6 bits)
repeat_indicator = 0 # 转发指示符 (2 bits)
user_id = 123456789 # 用户ID/MMSI (30 bits)
navigation_status = 8 # 导航状态 (4 bits) - 航行中
rot = -128 # 旋转速率 (8 bits) - 无信息
sog = 102 # 地面航速 (10 bits) - 10.2节
position_accuracy = 1 # 位置准确度 (1 bit) - 高
longitude = 120.5 # 经度 (28 bits) - 东经120.5°
latitude = 30.5 # 纬度 (27 bits) - 北纬30.5°
cog = 900 # 地面航线 (12 bits) - 90.0°
true_heading = 90 # 实际航向 (9 bits) - 90°
timestamp = 30 # 时戳 (6 bits) - UTC秒
special_maneuver = 0 # 特定操纵指示符 (2 bits)
spare = 0 # 备用 (3 bits)
raim_flag = 0 # RAIM标志 (1 bit)
comm_state = 0 # 通信状态 (19 bits)
# 添加各个字段(按照协议顺序)
bits.append(format(message_id, '06b')) # 消息ID
bits.append(format(repeat_indicator, '02b')) # 转发指示符
bits.append(format(user_id, '030b')) # 用户ID
bits.append(format(navigation_status, '04b')) # 导航状态
# 旋转速率 (8位有符号整数)
rot_bits = rot & 0xFF
bits.append(format(rot_bits, '08b'))
# 地面航速 (10位)
bits.append(format(min(sog, 1023), '010b'))
# 位置准确度 (1位)
bits.append(str(position_accuracy))
# 经度 (28位)
# 转换为1/10,000分钟单位
longitude_min = int(longitude * 60 * 10000)
bits.append(format(longitude_min & 0x0FFFFFFF, '028b'))
# 纬度 (27位)
latitude_min = int(latitude * 60 * 10000)
bits.append(format(latitude_min & 0x07FFFFFF, '027b'))
# 地面航线 (12位)
bits.append(format(min(cog, 3600), '012b'))
# 实际航向 (9位)
bits.append(format(min(true_heading, 511), '09b'))
# 时戳 (6位)
bits.append(format(min(timestamp, 63), '06b'))
# 特定操纵指示符 (2位)
bits.append(format(special_maneuver, '02b'))
# 备用 (3位)
bits.append(format(spare, '03b'))
# RAIM标志 (1位)
bits.append(str(raim_flag))
# 通信状态 (19位)
bits.append(format(comm_state, '019b'))
# 合并所有位
bit_string = ''.join(bits)
# 验证总位数
total_bits = len(bit_string)
if total_bits != 168:
print(f"警告: 总位数应为168实际为{total_bits}")
# 将位字符串转换为字节
binary_int = int(bit_string, 2) # 将二进制字符串转换为整数
byte_length = (len(bit_string) + 7) // 8 # 计算需要的字节数
binary_data = binary_int.to_bytes(byte_length, 'big') # 转换为字节
return binary_data
# 生成AIS报文
demod_content = encode_demod_fields()
ais_data = create_ais_info_packet(demod_content)
ais_packet = create_tcp_packet(12, ais_data)
# print("完整报文字节长度:", len(final_packet))
# print("二进制表示:")
# print(final_packet)
# print(' '.join(f'{b:02x}' for b in final_packet))
# print('----------------------------------/n')
# 生成GPS报文
gps_content = create_gps_packet()
gps_packet = create_tcp_packet(7, gps_content)
# 打印二进制报文
# print("完整报文字节长度:", len(gps_packet))
# print("二进制表示:")
# print(gps_packet)
# print(' '.join(f'{b:02x}' for b in gps_packet))
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
get_tcp_data(ais_packet)
# def get_demod_data(bit_string):
# pos = 0
# message_id = int(bit_string[pos:pos+6], 2) # 消息ID (6 bits)
# pos += 6
# repeat_indicator = int(bit_string[pos:pos+2], 2) # 转发指示符 (2 bits)
# pos += 2
# user_id = int(bit_string[pos:pos+30], 2) # 用户ID/MMSI (30 bits)
# pos += 30
# navigation_status = int(bit_string[pos:pos+4], 2) # 导航状态 (4 bits) - 航行中
# pos += 4
# rot_value = int(bit_string[pos:pos+8], 2)
# # 转换为有符号整数
# if rot_value > 127:
# rot_value -= 256
# rot = rot_value # 旋转速率 (8 bits) - 无信息
# pos += 8
# sog = int(bit_string[pos:pos+10], 2) # 地面航速 (10 bits) - 10.2节
# pos += 10
# position_accuracy = int(bit_string[pos], 2) # 位置准确度 (1 bit) - 高
# pos += 1
# longitude_value = int(bit_string[pos:pos+28], 2)
# # 转换为度
# longitude_deg = longitude_value / (60 * 10000)
# longitude = longitude_deg # 经度 (28 bits) - 东经120.5°
# pos += 28
# latitude_value = int(bit_string[pos:pos+27], 2)
# # 转换为度
# latitude_deg = latitude_value / (60 * 10000)
# latitude = latitude_deg # 纬度 (27 bits) - 北纬30.5°
# pos += 27
# cog = int(bit_string[pos:pos+12], 2) # 地面航线 (12 bits) - 90.0°
# pos += 12
# true_heading = int(bit_string[pos:pos+9], 2) # 实际航向 (9 bits) - 90°
# pos += 9
# timestamp = int(bit_string[pos:pos+6], 2) # 时戳 (6 bits) - UTC秒
# pos += 6
# special_maneuver = int(bit_string[pos:pos+2], 2) # 特定操纵指示符 (2 bits)
# pos += 2
# spare = int(bit_string[pos:pos+3], 2) # 备用 (3 bits)
# pos += 3
# raim_flag = int(bit_string[pos], 2) # RAIM标志 (1 bit)
# pos += 1
# comm_state = int(bit_string[pos:pos+19], 2) # 通信状态 (19 bits)