import struct import math def create_tcp_packet(packet_type, content): """创建符合VDES TCP协议的报文""" # 报文帧头 (4字节) header = b'####' # 报文类型 (4字节,大端) type_field = struct.pack('>I', packet_type) # 报文长度 (4字节,大端,内容长度) length = len(content) length_field = struct.pack('>I', length) # 构建完整报文 packet = header + type_field + length_field + content return packet def create_gps_packet(): """创建GPS解析数据报文(类型7)的内容""" # 模拟GPS数据 (表11定义) utc_time = 1680000000 # UTC时间 (8字节) longitude = 1205000000 # 经度 (4字节,东经120.5度) latitude = 305000000 # 纬度 (4字节,北纬30.5度) altitude = 50 # 海拔高度 (4字节,50米) used_sats = 10 # 定位使用的卫星数 (2字节) gps_sats = 8 # GPS卫星数 (2字节) beidou_sats = 7 # 北斗卫星数 (2字节) gps_status = 1 # GPS状态 (1字节,单点定位) position_mode = 3 # 定位模式 (1字节,3D定位) hdop = 2550 # 水平精度因子 (4字节,25.5米) speed = 1024 # 运动速度 (4字节,10.24节) direction = 359 # 运动方向 (4字节,359度) # 打包为二进制 (大端字节序) content = struct.pack( '>QiiiHHHBBIII', # 格式: Q(8),i(4),i(4),i(4),H(2),H(2),H(2),B(1),B(1),I(4),I(4),I(4) utc_time, longitude, latitude, altitude, used_sats, gps_sats, beidou_sats, gps_status, position_mode, hdop, speed, direction ) return content def create_ais_info_packet(demod_content): """创建解调信息报文(类型12)的内容""" # 模拟解调信息数据 message_type = 12 # 消息类型 (1字节) satellite_id = 1 # 卫星ID (1字节) demodulator_id = 0 # 解调器编号 (1字节) demod_slot = 1234 # 解调时隙 (2字节) receive_delay = 5678 # 接收延迟 (2字节,单位us) snr = 25.75 # 信噪比 (2字节,dB) # 处理信噪比 (高8位整数部分,低8位小数部分) snr_int = int(snr) snr_frac = int((snr - snr_int) * 100) # 转换为0-99的小数部分 snr_packed = (snr_int & 0xFF) << 8 | (snr_frac & 0xFF) # 打包为二进制 (大端字节序) content = struct.pack( '>BBBHHH', # 格式: B(1),B(1),B(1),H(2),H(2),h(2) message_type, satellite_id, demodulator_id, demod_slot, receive_delay, snr_packed ) return content + demod_content def encode_demod_fields(): """编码解调信息字段并打印解码结果""" # 初始化二进制位列表 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}") # 将位字符串转换为字节 binary_int = int(bit_string, 2) # 将二进制字符串转换为整数 byte_length = (len(bit_string) + 7) // 8 # 计算需要的字节数 binary_data = binary_int.to_bytes(byte_length, 'big') # 转换为字节 return binary_data # 生成AIS报文 demod_content = encode_demod_fields() ais_data = create_ais_info_packet(demod_content) ais_packet = create_tcp_packet(12, ais_data) # print("完整报文字节长度:", len(final_packet)) # print("二进制表示:") # print(final_packet) # print(' '.join(f'{b:02x}' for b in final_packet)) # print('----------------------------------/n') # 生成GPS报文 gps_content = create_gps_packet() gps_packet = create_tcp_packet(7, gps_content) # 打印二进制报文 # print("完整报文字节长度:", len(gps_packet)) # print("二进制表示:") # print(gps_packet) # print(' '.join(f'{b:02x}' for b in gps_packet)) def get_tcp_data(packet_data): #判断帧头是否符合卓研 if packet_data[:4].decode('ascii') == '####': print("开始解析报文帧") packet_type = struct.unpack('>I', packet_data[4:8])[0] #获取报文类型 7为gps, 12为ais packet_lenth = struct.unpack('>I', packet_data[8:12])[0] packet_content = packet_data[12:] if packet_type == 7: print(f"GPS内容长度: {packet_lenth} 字节") data = get_gps_data(packet_content) print(data) elif packet_type == 12: print(f"AIS内容长度: {packet_lenth} 字节") data = get_ais_data(packet_content) print(data) def get_gps_data(packet_content): fields = struct.unpack('>QiiiHHHBBIII', packet_content) res = {} res['utc_time'] = fields[0] # UTC时间 (8字节) res['longitude'] = fields[1]/10000000 # 经度 (4字节,东经120.5度) res['latitude'] = fields[2]/10000000 # 纬度 (4字节,北纬30.5度) res['altitude'] = fields[3] # 海拔高度 (4字节,50米) res['used_sats'] = fields[4] # 定位使用的卫星数 (2字节) res['gps_sats'] = fields[5] # GPS卫星数 (2字节) res['beidou_sats'] = fields[6] # 北斗卫星数 (2字节) res['gps_status'] = fields[7] # GPS状态 (1字节,单点定位) res['position_mode'] = fields[8] # 定位模式 (1字节,3D定位) res['hdop'] = fields[9]/10 # 水平精度因子 (4字节,25.5米) res['speed'] = fields[10]/100 # 运动速度 (4字节,10.24节) res['direction'] = fields[11] # 运动方向 (4字节,359度) return res def get_ais_data(packet_content): res ={} demod_packet = packet_content[:9] demod_data = packet_content[9:] fields = struct.unpack('>BBBHHH', demod_packet) res['message_type'] = fields[0] res['satellite_id'] = fields[1] res['demodulator_id'] = fields[2] res['demod_slot'] = fields[3] res['receive_delay'] = fields[4] snr_packed = fields[5] # 解析SNR snr_int = (snr_packed >> 8) & 0xFF snr_frac = snr_packed & 0xFF res['snr'] = snr_int + snr_frac / 100.0 print(demod_data) res['demod_data'] = get_demod_data(demod_data) return res def get_demod_data(bit_string): # 如果输入是字节类型,先转换为二进制字符串 if isinstance(bit_string, bytes): bit_string = ''.join(format(byte, '08b') for byte in bit_string) pos = 0 decoded = {} decoded['message_id'] = int(bit_string[pos:pos+6], 2) # 消息ID (6 bits) pos += 6 decoded['repeat_indicator'] = int(bit_string[pos:pos+2], 2) # 转发指示符 (2 bits) pos += 2 decoded['user_id'] = int(bit_string[pos:pos+30], 2) # 用户ID/MMSI (30 bits) pos += 30 decoded['navigation_status'] = int(bit_string[pos:pos+4], 2) # 导航状态 (4 bits) pos += 4 # 旋转速率 (8位有符号整数) rot_value = int(bit_string[pos:pos+8], 2) if rot_value > 127: rot_value -= 256 decoded['rot'] = rot_value pos += 8 decoded['sog'] = int(bit_string[pos:pos+10], 2) # 地面航速 (10 bits) pos += 10 decoded['position_accuracy'] = int(bit_string[pos], 2) # 位置准确度 (1 bit) pos += 1 # 经度 (28位) longitude_value = int(bit_string[pos:pos+28], 2) decoded['longitude'] = longitude_value / (60 * 10000) # 转换为度 pos += 28 # 纬度 (27位) latitude_value = int(bit_string[pos:pos+27], 2) decoded['latitude'] = latitude_value / (60 * 10000) # 转换为度 pos += 27 decoded['cog'] = int(bit_string[pos:pos+12], 2) # 地面航线 (12 bits) pos += 12 decoded['true_heading'] = int(bit_string[pos:pos+9], 2) # 实际航向 (9 bits) pos += 9 decoded['timestamp'] = int(bit_string[pos:pos+6], 2) # 时戳 (6 bits) pos += 6 decoded['special_maneuver'] = int(bit_string[pos:pos+2], 2) # 特定操纵指示符 (2 bits) pos += 2 decoded['spare'] = int(bit_string[pos:pos+3], 2) # 备用 (3 bits) pos += 3 decoded['raim_flag'] = int(bit_string[pos], 2) # RAIM标志 (1 bit) pos += 1 decoded['comm_state'] = int(bit_string[pos:pos+19], 2) # 通信状态 (19 bits) return decoded get_tcp_data(ais_packet) # def get_demod_data(bit_string): # pos = 0 # message_id = int(bit_string[pos:pos+6], 2) # 消息ID (6 bits) # pos += 6 # repeat_indicator = int(bit_string[pos:pos+2], 2) # 转发指示符 (2 bits) # pos += 2 # user_id = int(bit_string[pos:pos+30], 2) # 用户ID/MMSI (30 bits) # pos += 30 # navigation_status = int(bit_string[pos:pos+4], 2) # 导航状态 (4 bits) - 航行中 # pos += 4 # rot_value = int(bit_string[pos:pos+8], 2) # # 转换为有符号整数 # if rot_value > 127: # rot_value -= 256 # rot = rot_value # 旋转速率 (8 bits) - 无信息 # pos += 8 # sog = int(bit_string[pos:pos+10], 2) # 地面航速 (10 bits) - 10.2节 # pos += 10 # position_accuracy = int(bit_string[pos], 2) # 位置准确度 (1 bit) - 高 # pos += 1 # longitude_value = int(bit_string[pos:pos+28], 2) # # 转换为度 # longitude_deg = longitude_value / (60 * 10000) # longitude = longitude_deg # 经度 (28 bits) - 东经120.5° # pos += 28 # latitude_value = int(bit_string[pos:pos+27], 2) # # 转换为度 # latitude_deg = latitude_value / (60 * 10000) # latitude = latitude_deg # 纬度 (27 bits) - 北纬30.5° # pos += 27 # cog = int(bit_string[pos:pos+12], 2) # 地面航线 (12 bits) - 90.0° # pos += 12 # true_heading = int(bit_string[pos:pos+9], 2) # 实际航向 (9 bits) - 90° # pos += 9 # timestamp = int(bit_string[pos:pos+6], 2) # 时戳 (6 bits) - UTC秒 # pos += 6 # special_maneuver = int(bit_string[pos:pos+2], 2) # 特定操纵指示符 (2 bits) # pos += 2 # spare = int(bit_string[pos:pos+3], 2) # 备用 (3 bits) # pos += 3 # raim_flag = int(bit_string[pos], 2) # RAIM标志 (1 bit) # pos += 1 # comm_state = int(bit_string[pos:pos+19], 2) # 通信状态 (19 bits)