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) # 输出二进制数据