import struct import socket import time import random import math class Ship: def __init__(self, mmsi, lat, lon, heading, speed=280.24): self.mmsi = mmsi self.lat = lat self.lon = lon self.heading = heading self.speed = speed # 加速100倍用于演示 def update_position(self): """更新船只位置""" # 速度转换 speed_kmh = self.speed * 1.852 speed_kmps = speed_kmh / 3600 distance_km = speed_kmps * 1 # 航向转弧度 heading_rad = math.radians(self.heading) # 计算经纬度变化 delta_lat = distance_km / 111.0 * math.cos(heading_rad) delta_lon = distance_km / (111.0 * math.cos(math.radians(self.lat))) * math.sin(heading_rad) # 更新位置 self.lat += delta_lat self.lon += delta_lon return self.lon, self.lat class OwnShip(Ship): def __init__(self, lat, lon, heading, speed=280.24): super().__init__(336295999, lat, lon, heading, speed) # 使用固定MMSI作为本船 def get_position(self): """获取本船位置并更新""" return self.update_position() class VDESPacketCreator: @staticmethod def create_tcp_packet(packet_type, content): """创建符合VDES TCP协议的报文""" header = b'####' type_field = struct.pack('>I', packet_type) length_field = struct.pack('>I', len(content)) return header + type_field + length_field + content @classmethod def create_gps_packet(cls, own_ship): """创建GPS解析数据报文(类型7)的内容""" lon, lat = own_ship.get_position() # 打包GPS数据 return struct.pack( '>QiiiHHHBBIII', 1680000000, # UTC时间 int(lon * 10000000), # 经度 int(lat * 10000000), # 纬度 50, # 海拔高度 10, # 定位使用的卫星数 8, # GPS卫星数 7, # 北斗卫星数 1, # GPS状态 3, # 定位模式 2550, # 水平精度因子 1024, # 运动速度 own_ship.heading # 运动方向 ) @classmethod def create_ais_info_packet(cls, ship): """创建解调信息报文(类型12)的内容""" demod_content = cls.encode_demod_fields(ship) # 打包解调信息 message_type = 12 satellite_id = 1 demodulator_id = 0 demod_slot = 1234 receive_delay = 5678 snr = 25.75 # 处理信噪比 snr_int = int(snr) snr_frac = int((snr - snr_int) * 100) snr_packed = (snr_int & 0xFF) << 8 | (snr_frac & 0xFF) header = struct.pack( '>BBBHHH', message_type, satellite_id, demodulator_id, demod_slot, receive_delay, snr_packed ) return header + demod_content @staticmethod def encode_demod_fields(ship): """编码解调信息字段""" lon, lat = ship.update_position() # 准备数据 message_id = 1 repeat_indicator = 0 user_id = ship.mmsi navigation_status = 8 rot = -128 sog = 102 position_accuracy = 1 cog = ship.heading true_heading = ship.heading timestamp = 30 special_maneuver = 0 spare = 0 raim_flag = 0 comm_state = 0 # 转换为协议要求的格式 longitude_min = int(lon * 60 * 10000) latitude_min = int(lat * 60 * 10000) # 构建二进制位 bits = [ format(message_id, '06b'), format(repeat_indicator, '02b'), format(user_id, '030b'), format(navigation_status, '04b'), format(rot & 0xFF, '08b'), format(min(sog, 1023), '010b'), str(position_accuracy), format(longitude_min & 0x0FFFFFFF, '028b'), format(latitude_min & 0x07FFFFFF, '027b'), format(min(cog, 3600), '012b'), format(min(true_heading, 511), '09b'), format(min(timestamp, 63), '06b'), format(special_maneuver, '02b'), format(spare, '03b'), str(raim_flag), format(comm_state, '019b') ] # 合并所有位并转换为字节 bit_string = ''.join(bits) binary_int = int(bit_string, 2) byte_length = (len(bit_string) + 7) // 8 return binary_int.to_bytes(byte_length, 'big') class VDEServer: def __init__(self, host='127.0.0.1', port=10): self.host = host self.port = port self.own_ship = OwnShip(31.23, 123.87, 90) self.ships = self.create_ships(30) @staticmethod def create_ships(count): """创建指定数量的船只""" return [ Ship( mmsi=336295939 + i, lat=round(random.uniform(30.0, 34.0), 6), lon=round(random.uniform(123.5, 126.0), 6), heading=random.randint(0, 359) ) for i in range(count) ] def send_data_continuously(self): """启动Socket服务端并持续发送数据""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((self.host, self.port)) s.listen(1) print(f"Socket服务端已启动,监听 {self.host}:{self.port}") while True: try: conn, addr = s.accept() print(f"客户端连接来自: {addr}") while True: try: # 随机选择一艘船发送AIS报文 selected_ship = random.choice(self.ships) ais_data = VDESPacketCreator.create_ais_info_packet(selected_ship) ais_packet = VDESPacketCreator.create_tcp_packet(12, ais_data) conn.sendall(ais_packet) # 发送本船GPS报文 gps_content = VDESPacketCreator.create_gps_packet(self.own_ship) gps_packet = VDESPacketCreator.create_tcp_packet(7, gps_content) conn.sendall(gps_packet) time.sleep(0.5) except (ConnectionResetError, BrokenPipeError): print("客户端断开连接") break except KeyboardInterrupt: print("\n服务端已停止") break except Exception as e: print(f"服务端错误: {e}") break if __name__ == "__main__": server = VDEServer() server.send_data_continuously()