Files
VDES_Backend/报文模拟解析/develop/vdes_send.py

214 lines
7.2 KiB
Python
Raw Normal View History

2026-07-13 15:37:05 +08:00
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()