Files
VDES_Backend/报文模拟解析/demo1.py

271 lines
9.0 KiB
Python
Raw Normal View History

2026-07-13 15:37:05 +08:00
import struct
import math
def encode_ais_fields():
"""编码AIS消息字段并打印解码结果"""
# 初始化二进制位列表
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}")
# 将位字符串转换为字节
byte_count = total_bits // 8
ais_data = bytearray()
for i in range(byte_count):
byte_str = bit_string[i*8:(i+1)*8]
ais_data.append(int(byte_str, 2))
# 解码过程
decoded = {}
pos = 0
# 消息ID (6 bits)
decoded['消息ID'] = int(bit_string[pos:pos+6], 2)
pos += 6
# 转发指示符 (2 bits)
decoded['转发指示符'] = int(bit_string[pos:pos+2], 2)
pos += 2
# 用户ID (30 bits)
decoded['用户ID'] = int(bit_string[pos:pos+30], 2)
pos += 30
# 导航状态 (4 bits)
decoded['导航状态'] = int(bit_string[pos:pos+4], 2)
pos += 4
# 旋转速率 (8 bits)
rot_value = int(bit_string[pos:pos+8], 2)
# 转换为有符号整数
if rot_value > 127:
rot_value -= 256
decoded['旋转速率'] = rot_value
pos += 8
# SOG (10 bits)
decoded['SOG'] = int(bit_string[pos:pos+10], 2)
pos += 10
# 位置准确度 (1 bit)
decoded['位置准确度'] = int(bit_string[pos], 2)
pos += 1
# 经度 (28 bits)
longitude_value = int(bit_string[pos:pos+28], 2)
# 转换为度
longitude_deg = longitude_value / (60 * 10000)
decoded['经度'] = longitude_deg
pos += 28
# 纬度 (27 bits)
latitude_value = int(bit_string[pos:pos+27], 2)
# 转换为度
latitude_deg = latitude_value / (60 * 10000)
decoded['纬度'] = latitude_deg
pos += 27
# COG (12 bits)
decoded['COG'] = int(bit_string[pos:pos+12], 2)
pos += 12
# 实际航向 (9 bits)
decoded['实际航向'] = int(bit_string[pos:pos+9], 2)
pos += 9
# 时戳 (6 bits)
decoded['时戳'] = int(bit_string[pos:pos+6], 2)
pos += 6
# 特定操纵指示符 (2 bits)
decoded['特定操纵指示符'] = int(bit_string[pos:pos+2], 2)
pos += 2
# 备用 (3 bits)
decoded['备用'] = int(bit_string[pos:pos+3], 2)
pos += 3
# RAIM标志 (1 bit)
decoded['RAIM标志'] = int(bit_string[pos], 2)
pos += 1
# 通信状态 (19 bits)
decoded['通信状态'] = int(bit_string[pos:pos+19], 2)
# 打印结果
print("\n编码字段的二进制表示:")
print(bit_string[:6] + " " + bit_string[6:8] + " " + bit_string[8:38] + " " +
bit_string[38:42] + " " + bit_string[42:50] + " " + bit_string[50:60] + " " +
bit_string[60:61] + " " + bit_string[61:89] + " " + bit_string[89:116] + " " +
bit_string[116:128] + " " + bit_string[128:137] + " " + bit_string[137:143] + " " +
bit_string[143:145] + " " + bit_string[145:148] + " " + bit_string[148:149] + " " +
bit_string[149:])
print("\n解码结果:")
print(f"消息ID: {decoded['消息ID']} (1=AIS消息1)")
print(f"转发指示符: {decoded['转发指示符']} (0=默认)")
print(f"用户ID (MMSI): {decoded['用户ID']}")
# 导航状态描述
nav_status_desc = {
0: "发动机使用中", 1: "锚泊", 2: "未操纵", 3: "有限适航性",
4: "受船舶吃水限制", 5: "系泊", 6: "搁浅", 7: "从事捕捞",
8: "航行中", 15: "未规定(默认)"
}
status = decoded['导航状态']
print(f"导航状态: {status} ({nav_status_desc.get(status, '未知状态')})")
# 旋转速率描述
rot = decoded['旋转速率']
if rot == -128:
rot_desc = "无可用旋转信息(默认)"
elif rot == 127:
rot_desc = "右旋超过5º/30s"
elif rot == -127:
rot_desc = "左旋超过5º/30s"
else:
# 计算实际旋转速度
rot_speed = (rot/4.733)**2 if rot != 0 else 0
direction = "右旋" if rot > 0 else "左旋"
rot_desc = f"{direction} {abs(rot_speed):.1f} 度/分钟"
print(f"旋转速率: {rot} ({rot_desc})")
# SOG描述
sog_val = decoded['SOG']
if sog_val == 1023:
sog_desc = "不可用"
elif sog_val == 1022:
sog_desc = "102.2节或更快"
else:
sog_desc = f"{sog_val/10:.1f}"
print(f"SOG: {sog_val} ({sog_desc})")
print(f"位置准确度: {decoded['位置准确度']} ({'高(>10m)' if decoded['位置准确度'] else '低(<10m)'})")
print(f"经度: {decoded['经度']:.5f}° ({'东经' if decoded['经度'] >= 0 else '西经'})")
print(f"纬度: {decoded['纬度']:.5f}° ({'北纬' if decoded['纬度'] >= 0 else '南纬'})")
# COG描述
cog_val = decoded['COG']
if cog_val == 3600:
cog_desc = "不可用(默认)"
else:
cog_desc = f"{cog_val/10:.1f}°"
print(f"COG: {cog_val} ({cog_desc})")
# 实际航向描述
heading = decoded['实际航向']
heading_desc = "不可用(默认)" if heading == 511 else f"{heading}°"
print(f"实际航向: {heading} ({heading_desc})")
# 时戳描述
ts = decoded['时戳']
ts_desc = {
60: "时戳不可用",
61: "人工输入模式",
62: "航迹推算模式",
63: "定位系统不起作用"
}.get(ts, f"{ts}")
print(f"时戳: {ts} ({ts_desc})")
# 特定操纵指示符描述
maneuver = decoded['特定操纵指示符']
maneuver_desc = {
0: "不可用(默认)",
1: "未进行特定操纵",
2: "进行特定操纵"
}.get(maneuver, "未知")
print(f"特定操纵指示符: {maneuver} ({maneuver_desc})")
print(f"备用: {decoded['备用']} (未使用)")
print(f"RAIM标志: {decoded['RAIM标志']} ({'RAIM正在使用' if decoded['RAIM标志'] else 'RAIM未使用(默认)'})")
print(f"通信状态: {decoded['通信状态']} (见表49)")
# 打印二进制字节
print("\n二进制字节表示 (168 bits = 21 bytes):")
hex_str = ' '.join(f'{b:02x}' for b in ais_data)
print(hex_str)
return ais_data
# 执行编码和解码
ais_binary = encode_ais_fields()
binary_str = "000001000001110101101111001101000101011000100000000001100110101000100111100110101111000000010001011100111100011000000011100001000010110100111100000000000000000000000000"
binary_int = int(binary_str, 2) # 将二进制字符串转换为整数
byte_length = (len(binary_str) + 7) // 8 # 计算需要的字节数
binary_data = binary_int.to_bytes(byte_length, 'big') # 转换为字节
print(binary_data) # 输出二进制数据