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

153 lines
5.8 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 random
import struct
def generate_ais_message1():
"""生成AIS Message1位置报告 (M.1371-5 Annex8 3.1)"""
# 随机位置
lat, lon = 124, 30
# 转换为AIS格式
lat_ais = int((lat + 90) * 60000)
lon_ais = int((lon + 180) * 60000)
# 随机选择一艘船
mmsi = 200000000
COMM_STATES = [
{"sync_state": 0, "slot_timeout": 0, "sub_message": 0},
{"sync_state": 1, "slot_timeout": 1, "sub_message": 1},
{"sync_state": 2, "slot_timeout": 2, "sub_message": 2},
{"sync_state": 3, "slot_timeout": 3, "sub_message": 3}
]
# 随机通信状态
comm_state = random.choice(COMM_STATES)
comm_state_field = (
(comm_state["sync_state"] << 17) |
(comm_state["slot_timeout"] << 14) |
comm_state["sub_message"]
)
# 构建Message1 (168位/21字节)
msg = struct.pack('>I', (1 << 26) | (random.randint(0, 3) << 24) | (mmsi >> 6))
msg += struct.pack('>I', ((mmsi & 0x3F) << 26) | (random.randint(0, 15) << 22))
msg += struct.pack('>I', (random.randint(0, 255) << 24) | (random.randint(0, 1023) << 14))
msg += struct.pack('>I', (random.randint(0, 1) << 31) | (lon_ais & 0xFFFFFFF))
msg += struct.pack('>I', (lat_ais << 4) | (random.randint(0, 4095) >> 8))
msg += struct.pack('>I', ((random.randint(0, 4095) & 0xFF) << 24) | (random.randint(0, 3599) << 12))
msg += struct.pack('>I', (random.randint(0, 511) << 23) | (random.randint(0, 63) << 17) | (comm_state_field & 0x1FFFF))
return msg
gam = generate_ais_message1()
print(gam)
print(type(gam), len(gam))
def decode_ais_message1(data):
"""解码AIS Message1位置报告 (M.1371-5 Annex8 3.1)"""
# if len(data) != 21:
# raise ValueError("AIS消息1应为21字节")
# 将数据转换为整数列表
parts = [int.from_bytes(data[i:i+4], 'big') for i in range(0, 20, 4)]
parts.append(int.from_bytes(data[20:], 'big') << 24) # 最后一个字节
# 解码字段
decoded = {}
# 第一部分消息ID + 转发指示符 + MMSI高24位
decoded['message_id'] = (parts[0] >> 26) & 0x3F
decoded['repeat_indicator'] = (parts[0] >> 24) & 0x03
decoded['user_id'] = ((parts[0] & 0x00FFFFFF) << 6)
# 第二部分MMSI低6位 + 导航状态 + 旋转速率 + SOG高4位
decoded['user_id'] |= (parts[1] >> 26) & 0x3F
decoded['nav_status'] = (parts[1] >> 22) & 0x0F
rot_value = (parts[1] >> 14) & 0xFF
decoded['rot'] = rot_value if rot_value < 128 else rot_value - 256
decoded['sog'] = ((parts[1] & 0x00003F00) >> 8) << 6
# 第三部分SOG低6位 + 位置准确度 + 经度高21位
decoded['sog'] |= (parts[2] >> 26) & 0x3F
decoded['pos_acc'] = (parts[2] >> 25) & 0x01
decoded['longitude'] = ((parts[2] & 0x01FFFFFF) << 7)
# 第四部分经度低7位 + 纬度
decoded['longitude'] |= (parts[3] >> 25) & 0x7F
decoded['latitude'] = parts[3] & 0x07FFFFFF
# 第五部分COG + 实际航向 + 时戳高3位
decoded['cog'] = (parts[4] >> 20) & 0x0FFF
decoded['true_heading'] = (parts[4] >> 11) & 0x01FF
decoded['timestamp'] = ((parts[4] & 0x00000700) >> 8) << 3
# 第六部分时戳低3位 + RAIM标志 + 通信状态高10位
decoded['timestamp'] |= (parts[5] >> 29) & 0x07
decoded['raim'] = (parts[5] >> 24) & 0x01
decoded['comm_state'] = ((parts[5] & 0x00FFFFFF) >> 14) << 9
# 第七部分通信状态低9位
decoded['comm_state'] |= (parts[6] >> 23) & 0x1FF
# 添加spare字段协议中为保留位固定为0
decoded['spare'] = 0
return decoded
# 示例数据(从您的生成函数中获取)
data = b'\x06/\xaf\x08\x03@\x00\x00\x11\x93\x80\x00\x80\xc0B\xc0\x0c>\xc4\x00*\x8e\xa0\x00\xba\x02@\x01'
# 解码数据
decoded = decode_ais_message1(data)
# 打印解码结果
print("解码结果:")
for field, value in decoded.items():
print(f"{field}: {value}")
# # 生成AIS消息使用您的函数
# data = generate_ais_message1()
# print("生成的二进制数据:", data)
# # 解码数据
# decoded = decode_ais_message1(data)
# # 打印格式化结果
# print("\n解码结果:")
# print(f"消息ID: {decoded['message_id']}")
# print(f"转发指示符: {decoded['repeat_indicator']}")
# print(f"用户ID (MMSI): {decoded['user_id']}")
# # 导航状态描述
# nav_status_desc = {
# 0: "发动机使用中", 1: "锚泊", 2: "未操纵", 3: "有限适航性",
# 4: "受船舶吃水限制", 5: "系泊", 6: "搁浅", 7: "从事捕捞",
# 8: "航行中", 15: "未规定(默认)"
# }
# print(f"导航状态: {decoded['nav_status']} ({nav_status_desc.get(decoded['nav_status'], '未知状态')})")
# # 旋转速率描述
# rot = decoded['rot']
# if rot == -128:
# print("旋转速率: -128 (无可用旋转信息)")
# elif rot == 127:
# print("旋转速率: 127 (右旋超过5º/30s)")
# elif rot == -127:
# print("旋转速率: -127 (左旋超过5º/30s)")
# else:
# print(f"旋转速率: {rot}")
# # 位置准确度描述
# print(f"位置准确度: {decoded['pos_acc']} ({'高(>10m)' if decoded['pos_acc'] else '低(<10m)'})")
# # 转换为实际单位
# longitude_deg = decoded['longitude'] / (60 * 10000)
# latitude_deg = decoded['latitude'] / (60 * 10000)
# sog_knots = decoded['sog'] / 10.0
# cog_deg = decoded['cog'] / 10.0
# print(f"经度: {decoded['longitude']} (1/10,000 min) ≈ {longitude_deg:.5f}°")
# print(f"纬度: {decoded['latitude']} (1/10,000 min) ≈ {latitude_deg:.5f}°")
# print(f"地面航速: {decoded['sog']} (1/10节) ≈ {sog_knots:.1f}节")
# print(f"地面航线: {decoded['cog']} (1/10°) ≈ {cog_deg:.1f}°")
# print(f"实际航向: {decoded['true_heading']}°")
# print(f"时戳: {decoded['timestamp']}秒")
# print(f"RAIM标志: {decoded['raim']} ({'RAIM正在使用' if decoded['raim'] else 'RAIM未使用'})")
# print(f"通信状态: {decoded['comm_state']}")