137 lines
4.7 KiB
Python
137 lines
4.7 KiB
Python
|
|
"""
|
|||
|
|
模块1:UDP接收模块
|
|||
|
|
监听38101端口,接收来自主控的控制指令
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import socket
|
|||
|
|
import threading
|
|||
|
|
import logging
|
|||
|
|
from typing import Callable, Optional
|
|||
|
|
from data_structures import ControlPacket, CONTROL_RX_PORT
|
|||
|
|
|
|||
|
|
|
|||
|
|
class UDPReceiver:
|
|||
|
|
"""UDP接收模块"""
|
|||
|
|
|
|||
|
|
def __init__(self, local_ip: str = '0.0.0.0', port: int = CONTROL_RX_PORT, callback: Optional[Callable] = None):
|
|||
|
|
"""
|
|||
|
|
初始化接收模块
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
local_ip: 本地监听IP
|
|||
|
|
port: 监听端口
|
|||
|
|
callback: 接收到数据后的回调函数,签名为 callback(packet, remote_addr)
|
|||
|
|
"""
|
|||
|
|
self.local_ip = local_ip
|
|||
|
|
self.port = port
|
|||
|
|
self.callback = callback
|
|||
|
|
self.socket = None
|
|||
|
|
self.running = False
|
|||
|
|
self.receive_thread = None
|
|||
|
|
|
|||
|
|
# 配置日志
|
|||
|
|
self.logger = logging.getLogger(f'Module1-Receiver:{port}')
|
|||
|
|
self.logger.setLevel(logging.INFO)
|
|||
|
|
if not self.logger.handlers:
|
|||
|
|
handler = logging.StreamHandler()
|
|||
|
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|||
|
|
handler.setFormatter(formatter)
|
|||
|
|
self.logger.addHandler(handler)
|
|||
|
|
|
|||
|
|
def start(self):
|
|||
|
|
"""启动接收模块"""
|
|||
|
|
if self.running:
|
|||
|
|
self.logger.warning("Receiver is already running")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 创建UDP套接字
|
|||
|
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|||
|
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|||
|
|
self.socket.bind((self.local_ip, self.port))
|
|||
|
|
|
|||
|
|
self.running = True
|
|||
|
|
self.logger.info(f"Receiver started on port {self.port}")
|
|||
|
|
|
|||
|
|
# 启动接收线程
|
|||
|
|
self.receive_thread = threading.Thread(target=self._receive_loop, daemon=True)
|
|||
|
|
self.receive_thread.start()
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
self.logger.error(f"Failed to start receiver: {e}")
|
|||
|
|
self.running = False
|
|||
|
|
raise
|
|||
|
|
|
|||
|
|
def stop(self):
|
|||
|
|
"""停止接收模块"""
|
|||
|
|
self.running = False
|
|||
|
|
if self.socket:
|
|||
|
|
self.socket.close()
|
|||
|
|
if self.receive_thread:
|
|||
|
|
self.receive_thread.join(timeout=2)
|
|||
|
|
self.logger.info("Receiver stopped")
|
|||
|
|
|
|||
|
|
def _receive_loop(self):
|
|||
|
|
"""接收循环"""
|
|||
|
|
while self.running:
|
|||
|
|
try:
|
|||
|
|
# 接收数据(最大1472字节)
|
|||
|
|
data, remote_addr = self.socket.recvfrom(2048)
|
|||
|
|
|
|||
|
|
self.logger.info(f"Received {len(data)} bytes from {remote_addr}")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 解析控制包
|
|||
|
|
packet = ControlPacket.from_bytes(data)
|
|||
|
|
self.logger.info(f"Control packet parsed successfully")
|
|||
|
|
self.logger.debug(f" Device: {packet.device_number}")
|
|||
|
|
self.logger.debug(f" Work Mode: {packet.control_data.work_mode}")
|
|||
|
|
self.logger.debug(f" Work Instruction: {packet.control_data.work_instruction}")
|
|||
|
|
|
|||
|
|
# 调用回调函数
|
|||
|
|
if self.callback:
|
|||
|
|
self.callback(packet, remote_addr)
|
|||
|
|
|
|||
|
|
except ValueError as e:
|
|||
|
|
self.logger.error(f"Failed to parse control packet: {e}")
|
|||
|
|
self.logger.debug(f"Raw data (hex): {data.hex()}")
|
|||
|
|
|
|||
|
|
except socket.timeout:
|
|||
|
|
continue
|
|||
|
|
except Exception as e:
|
|||
|
|
if self.running:
|
|||
|
|
self.logger.error(f"Error in receive loop: {e}")
|
|||
|
|
break
|
|||
|
|
|
|||
|
|
def set_callback(self, callback: Callable):
|
|||
|
|
"""设置接收回调函数"""
|
|||
|
|
self.callback = callback
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
# 配置日志
|
|||
|
|
logging.basicConfig(level=logging.INFO)
|
|||
|
|
|
|||
|
|
def on_packet_received(packet, remote_addr):
|
|||
|
|
"""处理接收到的包"""
|
|||
|
|
print(f"\n=== Packet Received from {remote_addr} ===")
|
|||
|
|
print(f"Device Number: {packet.device_number}")
|
|||
|
|
print(f"Work Mode: {packet.control_data.work_mode}")
|
|||
|
|
print(f"Work Instruction: {packet.control_data.work_instruction}")
|
|||
|
|
print(f"Imaging Mode: {packet.control_data.imaging_mode}")
|
|||
|
|
print(f"Route Number: {packet.control_data.route_number}")
|
|||
|
|
print(f"Route Count: {packet.control_data.route_count}")
|
|||
|
|
|
|||
|
|
# 创建并启动接收模块
|
|||
|
|
receiver = UDPReceiver(callback=on_packet_received)
|
|||
|
|
receiver.start()
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 保持运行
|
|||
|
|
import time
|
|||
|
|
while True:
|
|||
|
|
time.sleep(1)
|
|||
|
|
except KeyboardInterrupt:
|
|||
|
|
print("\nShutting down...")
|
|||
|
|
receiver.stop()
|