Files
2026-07-13 15:37:05 +08:00

271 lines
9.0 KiB
Python
Raw Permalink 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 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) # 输出二进制数据