Files
VDES_Backend/协议资料/zhuoyan_model(1).py
2026-07-13 15:37:05 +08:00

354 lines
14 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 socket
import threading
import queue
import random
import struct
import time
import math
from datetime import datetime
# 全局配置
HOST = 'localhost'
PORT = 10
BUFFER_SIZE = 32768
FRAME_HEADER = b'####'
# 长江入海口位置 (中心点)
YANGTZE_ESTUARY_LAT = 31.23
YANGTZE_ESTUARY_LON = 121.47
RANGE_NM = 5 # 5海里范围
# 预生成10艘船的MMSI
SHIP_MMSIS = [random.randint(200000000, 299999999) for _ in range(10)]
# 报文类型定义
MSG_TYPE_DEBUG = 0
MSG_TYPE_LVDS = 1
MSG_TYPE_CAN = 2
MSG_TYPE_AD9361 = 3
MSG_TYPE_WAVE_CTRL = 4
MSG_TYPE_TEST_PARAM = 5
MSG_TYPE_TEST_WAVE = 6
MSG_TYPE_GPS = 7
MSG_TYPE_STATUS = 8
MSG_TYPE_VDES_CTRL = 9
MSG_TYPE_VDES_UPLOAD = 10
MSG_TYPE_COLLECT = 11
MSG_TYPE_DEMOD = 12
MSG_TYPE_NOTIFY = 13
# 解调器类型
DEMOD_VDES = 0 # VDES解调器 (0-3)
DEMOD_AIS = 4 # AIS解调器 (4-5)
# 通信状态定义 (Annex 2 Table 18)
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}
]
class VDESTCPServer:
def __init__(self):
self.send_queue = queue.Queue()
self.running = True
self.device_state = {
"cpu0": 50,
"cpu1": 50,
"version": 0x01020304,
"uptime": int(time.time()),
"gps_status": 1,
"pps_lock": 1,
"ad9361_status": 2
}
self.gps_params = self.generate_gps_data()
def start(self):
# server_thread = threading.Thread(target=self.run_server)
# server_thread.daemon = True
# server_thread.start()
# send_thread = threading.Thread(target=self.send_data_thread)
# send_thread.daemon = True
# send_thread.start()
# server_thread.join()
# send_thread.join()
print(11111111111)
print(self.build_gps_message())
def run_server(self):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
print(f"VDES TCP Server listening on {HOST}:{PORT}")
while self.running:
conn, addr = s.accept()
print(f"Connected by {addr}")
client_thread = threading.Thread(target=self.handle_client, args=(conn,))
client_thread.daemon = True
client_thread.start()
def handle_client(self, conn):
with conn:
while self.running:
try:
data = conn.recv(BUFFER_SIZE)
if not data:
break
# 解析报文
if len(data) < 12:
print("Invalid packet size")
continue
header = data[:4]
if header != FRAME_HEADER:
print("Invalid frame header")
continue
msg_type = struct.unpack('>I', data[4:8])[0]
msg_len = struct.unpack('>I', data[8:12])[0]
msg_content = data[12:12+msg_len] if msg_len > 0 else b''
print(f"Received message type: {msg_type}, length: {msg_len}")
# 处理报文并准备响应
response = self.process_message(msg_type, msg_content)
if response:
self.send_queue.put(response)
except Exception as e:
print(f"Error handling client: {e}")
break
def process_message(self, msg_type, content):
"""处理接收到的报文并返回响应"""
response = None
if msg_type == MSG_TYPE_DEBUG:
# 调试指令报文
if len(content) >= 1:
cmd_type = content[0]
print(f"Received debug command: {cmd_type}")
# 简单响应通知报文
response = self.build_notify_message(0, "Debug command processed")
elif msg_type == MSG_TYPE_AD9361:
# AD9361参数控制
print("Received AD9361 control params")
response = self.build_notify_message(0, "AD9361 params updated")
elif msg_type == MSG_TYPE_TEST_PARAM:
# 发送测试参数控制
if len(content) >= 9:
test_type, test_count, test_interval = struct.unpack('>BII', content[:9])
print(f"Test params: type={test_type}, count={test_count}, interval={test_interval}ms")
response = self.build_notify_message(0, "Test params accepted")
elif msg_type == MSG_TYPE_VDES_CTRL:
# VDES协议参数控制
print("Received VDES control params")
response = self.build_notify_message(0, "VDES params updated")
elif msg_type == MSG_TYPE_VDES_UPLOAD:
# VDES上注数据
if len(content) >= 1:
data_type = content[0]
print(f"VDES upload data type: {data_type}")
response = self.build_notify_message(0, "Data upload accepted")
return response
def send_data_thread(self):
"""发送线程定期发送GPS和解调数据报文"""
while self.running:
try:
# 发送GPS数据 (每秒一次)
self.gps_params = self.generate_gps_data()
gps_msg = self.build_gps_message()
self.send_queue.put(gps_msg)
# 发送解调数据 (随机间隔)
if random.random() > 0.7:
demod_msg = self.build_demod_message()
self.send_queue.put(demod_msg)
# 发送状态监控数据 (每秒一次)
status_msg = self.build_status_message()
self.send_queue.put(status_msg)
# 发送队列中的响应报文
while not self.send_queue.empty():
msg = self.send_queue.get()
# 在实际服务器中,这里应该发送给所有连接的客户端
# 本示例中仅打印发送信息
print(f"Sending message type: {struct.unpack('>I', msg[4:8])[0]}, "
f"length: {struct.unpack('>I', msg[8:12])[0]}")
time.sleep(1)
except Exception as e:
print(f"Error in send thread: {e}")
def build_packet(self, msg_type, content):
"""构建完整TCP报文"""
header = FRAME_HEADER
type_field = struct.pack('>I', msg_type)
length_field = struct.pack('>I', len(content))
return header + type_field + length_field + content
def build_gps_message(self):
"""构建GPS解析数据报文 (类型7)"""
content = struct.pack('>QiiihhhBBBBBB',
self.gps_params["utc_time"],
self.gps_params["longitude"],
self.gps_params["latitude"],
self.gps_params["altitude"],
self.gps_params["used_sats"],
self.gps_params["gps_sats"],
self.gps_params["beidou_sats"],
self.gps_params["gps_status"],
self.gps_params["fix_mode"],
self.gps_params["hdop"],
self.gps_params["speed"],
self.gps_params["course"])
return self.build_packet(MSG_TYPE_GPS, content)
def build_demod_message(self):
"""构建VDES解调数据报文 (类型12)"""
demod_id = random.randint(0, 5)
comm_state = random.choice(COMM_STATES)
if demod_id <= DEMOD_VDES + 3: # VDES解调器 (0-3)
# 根据M.2092-1 Annex5 3.10生成消息
msg_data = self.generate_vdes_message()
else: # AIS解调器 (4-5)
# 根据M.1371-5 Annex8 3.1生成Message1
msg_data = self.generate_ais_message1()
# 构建通信状态字段
comm_state_field = struct.pack('>BBH',
(comm_state["sync_state"] << 6) | (comm_state["slot_timeout"] << 3),
comm_state["sub_message"] >> 8,
comm_state["sub_message"] & 0xFF)
# 构建完整报文
content = struct.pack('>BBHH', 12, demod_id, random.randint(0, 65535), random.randint(0, 65535))
content += struct.pack('>H', random.randint(-12800, 12700)) # 信噪比
content += comm_state_field
content += msg_data
return self.build_packet(MSG_TYPE_DEMOD, content)
def build_status_message(self):
"""构建地检状态监控报文 (类型8)"""
# 更新设备状态
self.device_state["cpu0"] = random.randint(40, 60)
self.device_state["cpu1"] = random.randint(40, 60)
self.device_state["uptime"] = int(time.time())
# 构建报文内容 (简化版)
content = struct.pack('>BBIIBBBB',
self.device_state["cpu0"],
self.device_state["cpu1"],
self.device_state["version"],
self.device_state["uptime"],
self.device_state["gps_status"],
self.device_state["pps_lock"],
self.device_state["ad9361_status"],
0) # 校准因子占位
return self.build_packet(MSG_TYPE_STATUS, content)
def build_notify_message(self, msg_type, text):
"""构建消息通知报文 (类型13)"""
text_bytes = text.encode('utf-8')
content = struct.pack('>B', msg_type) + text_bytes
return self.build_packet(MSG_TYPE_NOTIFY, content)
def generate_gps_data(self):
"""生成GPS数据 (长江入海口5海里范围内)"""
# 在中心点附近5海里范围内生成随机位置
lat, lon = self.generate_random_position()
return {
"utc_time": int(time.time()),
"longitude": int(lon * 10000000),
"latitude": int(lat * 10000000),
"altitude": random.randint(-50, 100),
"used_sats": random.randint(5, 12),
"gps_sats": random.randint(3, 8),
"beidou_sats": random.randint(3, 8),
"gps_status": random.randint(0, 4),
"fix_mode": random.randint(1, 3),
"hdop": random.randint(10, 100),
"speed": random.randint(0, 2000), # 0.01节单位
"course": random.randint(0, 35900) # 0.01度单位
}
def generate_random_position(self):
"""在长江入海口5海里范围内生成随机位置"""
# 1海里 ≈ 0.0166667度 (赤道附近)
offset_lat = (random.random() - 0.5) * RANGE_NM * 0.0166667
offset_lon = (random.random() - 0.5) * RANGE_NM * 0.0166667
lat = YANGTZE_ESTUARY_LAT + offset_lat
lon = YANGTZE_ESTUARY_LON + offset_lon
return lat, lon
def generate_vdes_message(self):
"""生成VDES消息 (M.2092-1 Annex5 3.10)"""
# 随机选择一种消息类型 (简化实现)
msg_types = [0, 1, 2, 3, 4, 5]
msg_type = random.choice(msg_types)
# 构建基本消息结构
msg = struct.pack('>B', msg_type)
# 添加随机内容
if msg_type == 0: # Paging
msg += struct.pack('>I', random.randint(100000000, 999999999))
elif msg_type == 1: # Resource request
msg += struct.pack('>IB', random.randint(100000000, 999999999), random.randint(0, 255))
return msg
def generate_ais_message1(self):
"""生成AIS Message1位置报告 (M.1371-5 Annex8 3.1)"""
# 随机位置
lat, lon = self.generate_random_position()
# 转换为AIS格式
lat_ais = int((lat + 90) * 60000)
lon_ais = int((lon + 180) * 60000)
# 随机选择一艘船
mmsi = random.choice(SHIP_MMSIS)
# 随机通信状态
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
if __name__ == "__main__":
server = VDESTCPServer()
server.start()