first commit
This commit is contained in:
271
报文模拟解析/demo1.py
Normal file
271
报文模拟解析/demo1.py
Normal file
@@ -0,0 +1,271 @@
|
||||
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) # 输出二进制数据
|
||||
Reference in New Issue
Block a user