From 2fa19599467263dcf582bb12906e03328e03b4a4 Mon Sep 17 00:00:00 2001
From: zhang <zc857179121@qq.com>
Date: 星期三, 02 七月 2025 13:12:26 +0800
Subject: [PATCH] 初版提交

---
 algorithm_system/algorithm_server.py |  623 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 623 insertions(+), 0 deletions(-)

diff --git a/algorithm_system/algorithm_server.py b/algorithm_system/algorithm_server.py
new file mode 100644
index 0000000..f338288
--- /dev/null
+++ b/algorithm_system/algorithm_server.py
@@ -0,0 +1,623 @@
+"""
+绠楁硶绯荤粺鏈嶅姟鍣�
+"""
+import json
+import logging
+import os
+import time
+from typing import Dict, List, Optional, Any, Tuple
+from flask import Flask, request, jsonify
+
+from common.data_models import (
+    TaskData, AGVStatus, TaskAssignment, PlannedPath, 
+    create_success_response, create_error_response, ResponseCode, to_dict, from_dict
+)
+from common.utils import load_path_mapping
+from algorithm_system.models.agv_model import AGVModelManager
+from algorithm_system.algorithms.task_allocation import TaskAllocationFactory
+from algorithm_system.algorithms.path_planning import PathPlanningFactory
+from common.api_client import RCSAPIClient
+from algorithm_system.path_monitor import PathMonitorService
+
+try:
+    from config.settings import (
+        ALGORITHM_SERVER_HOST, ALGORITHM_SERVER_PORT,
+        RCS_SERVER_HOST, RCS_SERVER_PORT,
+        MONITOR_POLLING_INTERVAL
+    )
+except ImportError:
+    ALGORITHM_SERVER_HOST = "10.10.10.239"
+    ALGORITHM_SERVER_PORT = 8002
+    RCS_SERVER_HOST = "10.10.10.156"
+    RCS_SERVER_PORT = 8088
+    MONITOR_POLLING_INTERVAL = 5.0
+    logging.warning("鏃犳硶浠巆onfig.settings瀵煎叆閰嶇疆锛屼娇鐢ㄩ粯璁ゅ��")
+
+
+class AlgorithmServer:
+    """绠楁硶绯荤粺鏈嶅姟鍣�"""
+    
+    def __init__(self, host: str = None, port: int = None, enable_path_monitor: bool = True, 
+                 monitor_interval: float = None):
+        """鍒濆鍖栫畻娉曟湇鍔″櫒"""
+        self.host = host or ALGORITHM_SERVER_HOST
+        self.port = port or ALGORITHM_SERVER_PORT
+        self.enable_path_monitor = enable_path_monitor
+        self.monitor_interval = monitor_interval or MONITOR_POLLING_INTERVAL
+        self.logger = logging.getLogger(__name__)
+        
+        self.app = Flask(__name__)
+        
+        self.path_mapping = load_path_mapping()
+        
+        self.agv_manager = AGVModelManager(self.path_mapping)
+        
+        self.rcs_client = RCSAPIClient()
+        
+        self.task_allocation_algorithm = "LOAD_BALANCED"  # 榛樿浠诲姟鍒嗛厤
+        self.path_planning_algorithm = "A_STAR"  # 榛樿璺緞瑙勫垝
+
+        self.path_monitor = None
+        if self.enable_path_monitor:
+            self.path_monitor = PathMonitorService(
+                rcs_host=RCS_SERVER_HOST,
+                rcs_port=RCS_SERVER_PORT,
+                poll_interval=self.monitor_interval,
+                path_algorithm=self.path_planning_algorithm,
+                auto_send_paths=True  # 鑷姩鍙戦�佽矾寰勫埌RCS
+            )
+            self.logger.info(f"璺緞鐩戞帶鏈嶅姟宸插垵濮嬪寲 - 杞闂撮殧: {self.monitor_interval}s, 鑷姩鍙戦�佽矾寰�: True")
+        
+        self._setup_routes()
+        
+        self.logger.info("绠楁硶绯荤粺鏈嶅姟鍣ㄥ垵濮嬪寲瀹屾垚")
+    
+    def _setup_routes(self):
+        """璁剧疆API璺敱"""
+        
+        @self.app.route('/open/task/send/v1', methods=['POST'])
+        def task_send_endpoint():
+            """浠诲姟涓嬪彂鎺ュ彛"""
+            return self._handle_task_send_request()
+        
+        @self.app.route('/open/path/plan/v1', methods=['POST'])
+        def path_plan_endpoint():
+            """璺緞瑙勫垝鎺ュ彛"""
+            return self._handle_path_planning_request()
+        
+        @self.app.route('/open/path/batch/plan/v1', methods=['POST'])
+        def batch_path_plan_endpoint():
+            """鎵归噺璺緞瑙勫垝鎺ュ彛"""
+            return self._handle_batch_path_planning_request()
+        
+        @self.app.route('/open/algorithm/config/v1', methods=['POST'])
+        def algorithm_config_endpoint():
+            """绠楁硶閰嶇疆鎺ュ彛"""
+            return self._handle_algorithm_config_request()
+        
+        @self.app.route('/monitor/path/start/v1', methods=['POST'])
+        def start_path_monitor_endpoint():
+            """鍚姩璺緞鐩戞帶鏈嶅姟鎺ュ彛"""
+            return self._handle_start_path_monitor_request()
+        
+        @self.app.route('/monitor/path/stop/v1', methods=['POST'])
+        def stop_path_monitor_endpoint():
+            """鍋滄璺緞鐩戞帶鏈嶅姟鎺ュ彛"""
+            return self._handle_stop_path_monitor_request()
+        
+        @self.app.route('/monitor/path/status/v1', methods=['GET'])
+        def path_monitor_status_endpoint():
+            """璺緞鐩戞帶鏈嶅姟鐘舵�佹煡璇㈡帴鍙�"""
+            return self._handle_path_monitor_status_request()
+        
+        @self.app.route('/health', methods=['GET'])
+        def health_check():
+            """鍋ュ悍妫�鏌ユ帴鍙�"""
+            monitor_status = None
+            if self.path_monitor:
+                monitor_status = self.path_monitor.get_monitoring_status()
+            
+            return jsonify({
+                "status": "healthy", 
+                "service": "algorithm_system",
+                "timestamp": time.time(),
+                "path_mapping_loaded": len(self.path_mapping) > 0,
+                "algorithms": {
+                    "task_allocation": self.task_allocation_algorithm,
+                    "path_planning": self.path_planning_algorithm
+                },
+                "agv_count": len(self.agv_manager.get_all_agvs()),
+                "path_monitor": monitor_status,
+                "available_endpoints": [
+                    "POST /open/task/send/v1 - 浠诲姟鍒嗛厤鎺ュ彛",
+                    "POST /open/path/plan/v1 - 鍗曡矾寰勮鍒掓帴鍙�", 
+                    "POST /open/path/batch/plan/v1 - 鎵归噺璺緞瑙勫垝鎺ュ彛",
+                    "POST /open/algorithm/config/v1 - 绠楁硶閰嶇疆鎺ュ彛",
+                    "POST /monitor/path/start/v1 - 鍚姩璺緞鐩戞帶鏈嶅姟",
+                    "POST /monitor/path/stop/v1 - 鍋滄璺緞鐩戞帶鏈嶅姟",
+                    "GET /monitor/path/status/v1 - 璺緞鐩戞帶鏈嶅姟鐘舵�佹煡璇�",
+                    "GET /health - 鍋ュ悍妫�鏌ユ帴鍙�"
+                ]
+            })
+        
+        @self.app.errorhandler(404)
+        def not_found(error):
+            """404閿欒澶勭悊"""
+            return jsonify(to_dict(create_error_response(404, "鎺ュ彛涓嶅瓨鍦�"))), 404
+        
+        @self.app.errorhandler(500)
+        def internal_error(error):
+            """500閿欒澶勭悊"""
+            self.logger.error(f"鍐呴儴鏈嶅姟鍣ㄩ敊璇�: {error}")
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, "鍐呴儴鏈嶅姟鍣ㄩ敊璇�"))), 500
+    
+    def _handle_task_send_request(self) -> Dict[str, Any]:
+        """澶勭悊浠诲姟涓嬪彂璇锋眰"""
+        try:
+            if not request.is_json:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "璇锋眰鏁版嵁鏍煎紡閿欒")))
+            
+            request_data = request.get_json()
+            if not request_data:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "璇锋眰鏁版嵁涓虹┖")))
+            
+            if isinstance(request_data, dict) and "tasks" in request_data:
+                task_data = request_data.get("tasks", [])
+                agv_status_data = request_data.get("agvStatus", [])
+                self.logger.info(f"鏀跺埌缁撴瀯鍖栦换鍔″垎閰嶈姹傦紝浠诲姟鏁伴噺: {len(task_data)}, AGV鏁伴噺: {len(agv_status_data)}")
+            elif isinstance(request_data, list):
+                task_data = request_data
+                agv_status_data = []
+                self.logger.info(f"鏀跺埌浠诲姟鍒嗛厤璇锋眰锛屼换鍔℃暟閲�: {len(task_data)}")
+            else:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "浠诲姟鏁版嵁鏍煎紡鏃犳晥")))
+            
+            if not task_data or not isinstance(task_data, list):
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "浠诲姟鏁版嵁鏃犳晥")))
+            
+            tasks = []
+            for task_dict in task_data:
+                try:
+                    task = TaskData(
+                        taskId=task_dict.get("taskId", ""),
+                        start=task_dict.get("start", ""),
+                        end=task_dict.get("end", ""),
+                        type=task_dict.get("type", "1"),
+                        priority=task_dict.get("priority", 5)
+                    )
+                    tasks.append(task)
+                except Exception as e:
+                    self.logger.warning(f"瑙f瀽浠诲姟鏁版嵁澶辫触: {task_dict} - {e}")
+                    continue
+            
+            if not tasks:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "娌℃湁鏈夋晥鐨勪换鍔℃暟鎹�")))
+            
+            agv_status_list = []
+            if agv_status_data:
+                self.logger.info("浣跨敤璇锋眰涓彁渚涚殑AGV鐘舵�佹暟鎹�")
+                for agv_data in agv_status_data:
+                    try:
+                        agv_status = from_dict(AGVStatus, agv_data)
+                        agv_status_list.append(agv_status)
+                    except Exception as e:
+                        self.logger.warning(f"瑙f瀽璇锋眰涓殑AGV鐘舵�佹暟鎹け璐�: {agv_data} - {e}")
+                        continue
+            else:
+                self.logger.info("浠嶳CS绯荤粺鑾峰彇AGV鐘舵�佹暟鎹�")
+                agv_response = self.rcs_client.get_agv_status()
+                if agv_response.code == ResponseCode.SUCCESS and agv_response.data:
+                    for agv_data in agv_response.data:
+                        try:
+                            agv_status = from_dict(AGVStatus, agv_data)
+                            agv_status_list.append(agv_status)
+                        except Exception as e:
+                            self.logger.warning(f"瑙f瀽RCS杩斿洖鐨凙GV鐘舵�佹暟鎹け璐�: {agv_data} - {e}")
+                            continue
+                else:
+                    error_msg = f"鏃犳硶鑾峰彇AGV鐘舵��: {agv_response.msg if agv_response else 'RCS绯荤粺杩炴帴澶辫触'}"
+                    self.logger.error(error_msg)
+                    
+                    use_fallback_allocation = getattr(self, 'use_fallback_allocation', True)
+                    
+                    if use_fallback_allocation:
+                        self.logger.warning("浣跨敤杞鍒嗛厤浣滀负澶囩敤鏂规")
+                        return self._simple_round_robin_allocation(tasks)
+                    else:
+                        return jsonify(to_dict(create_error_response(
+                            ResponseCode.SERVER_ERROR, 
+                            error_msg
+                        )))
+            
+            if not agv_status_list:
+                return jsonify(to_dict(create_error_response(ResponseCode.NO_DATA, "娌℃湁鍙敤鐨凙GV鐘舵�佹暟鎹�")))
+            
+            self.agv_manager.update_agv_data(agv_status_list)
+            self.logger.info(f"鏇存柊浜� {len(agv_status_list)} 涓狝GV鐘舵��")
+            
+            all_agvs = self.agv_manager.get_all_agvs()
+            self.logger.info(f"绠楁硶绯荤粺涓綋鍓嶆湁 {len(all_agvs)} 涓狝GV妯″瀷")
+            
+            available_count = 0
+            for agv in all_agvs:
+                can_accept = agv.can_accept_task(5) 
+                self.logger.debug(f"AGV {agv.agvId}: status={agv.status}, can_accept_task={can_accept}, "
+                                f"is_overloaded={agv.is_overloaded()}, task_count={agv.current_task_count}")
+                if can_accept:
+                    available_count += 1
+            
+            self.logger.info(f"鍏朵腑 {available_count} 涓狝GV鍙互鎺ュ彈浠诲姟")
+            
+            if available_count == 0:
+                self.logger.warning("娌℃湁AGV鍙互鎺ュ彈浠诲姟锛佽缁嗙姸鎬�:")
+                for agv in all_agvs:
+                    status_str = str(agv.status)
+                    self.logger.warning(f"  AGV {agv.agvId}: 鐘舵��={status_str}, 绫诲瀷={type(agv.status)}, "
+                                      f"浠诲姟鏁�={agv.current_task_count}/{agv.max_capacity}")
+            
+            allocator = TaskAllocationFactory.create_allocator(
+                self.task_allocation_algorithm, 
+                self.agv_manager
+            )
+            
+            start_time = time.time()
+            assignments = allocator.allocate_tasks(tasks)
+            end_time = time.time()
+            
+            allocation_time = (end_time - start_time) * 1000  # 杞崲涓烘绉�
+            
+            assignment_data = [to_dict(assignment) for assignment in assignments]
+            
+            self.logger.info(f"浠诲姟鍒嗛厤瀹屾垚锛屽垎閰嶄簡 {len(assignments)} 涓换鍔★紝鑰楁椂: {allocation_time:.2f}ms")
+            
+            response = create_success_response(assignment_data)
+            return jsonify(to_dict(response))
+            
+        except Exception as e:
+            self.logger.error(f"澶勭悊浠诲姟鍒嗛厤璇锋眰澶辫触: {e}", exc_info=True)
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鏈嶅姟鍣ㄩ敊璇�: {str(e)}")))
+    
+    def _handle_path_planning_request(self) -> Dict[str, Any]:
+        """澶勭悊璺緞瑙勫垝璇锋眰"""
+        try:
+            # 楠岃瘉璇锋眰鏁版嵁
+            if not request.is_json:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "璇锋眰鏁版嵁鏍煎紡閿欒")))
+            
+            request_data = request.get_json()
+            if not request_data:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "璇锋眰鏁版嵁涓虹┖")))
+            
+            agv_id = request_data.get("agvId")
+            start_code = request_data.get("start")
+            end_code = request_data.get("end")
+            constraints = request_data.get("constraints", [])
+            
+            if not agv_id or not start_code or not end_code:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "缂哄皯蹇呰鍙傛暟")))
+            
+            self.logger.info(f"鏀跺埌璺緞瑙勫垝璇锋眰 - AGV: {agv_id}, 浠� {start_code} 鍒� {end_code}")
+            
+            # 鍒涘缓璺緞瑙勫垝鍣�
+            path_planner = PathPlanningFactory.create_path_planner(
+                self.path_planning_algorithm, 
+                self.path_mapping
+            )
+            
+            # 鎵ц璺緞瑙勫垝
+            start_time = time.time()
+            planned_path = path_planner.plan_path(start_code, end_code, constraints)
+            end_time = time.time()
+            
+            planning_time = (end_time - start_time) * 1000  # 杞崲涓烘绉�
+            
+            if planned_path:
+                # 璁剧疆AGV ID
+                planned_path.agvId = agv_id
+                
+                # 杞崲涓哄搷搴旀牸寮�
+                path_data = to_dict(planned_path)
+                
+                self.logger.info(f"璺緞瑙勫垝瀹屾垚 - AGV: {agv_id}, 璺緞闀垮害: {len(planned_path.codeList)}, 鑰楁椂: {planning_time:.2f}ms")
+                
+                response = create_success_response(path_data)
+                return jsonify(to_dict(response))
+            else:
+                self.logger.warning(f"璺緞瑙勫垝澶辫触 - AGV: {agv_id}, 浠� {start_code} 鍒� {end_code}")
+                return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, "鏃犳硶瑙勫垝璺緞")))
+                
+        except Exception as e:
+            self.logger.error(f"澶勭悊璺緞瑙勫垝璇锋眰澶辫触: {e}", exc_info=True)
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鏈嶅姟鍣ㄩ敊璇�: {str(e)}")))
+    
+    def _handle_batch_path_planning_request(self) -> Dict[str, Any]:
+        """澶勭悊鎵归噺璺緞瑙勫垝璇锋眰"""
+        try:
+            if not request.is_json:
+                request_data = {}
+            else:
+                request_data = request.get_json() or {}
+            
+            constraints = request_data.get("constraints", [])
+            include_idle_agv = request_data.get("includeIdleAgv", False)
+            use_enhanced_planning = request_data.get("useEnhancedPlanning", True)
+            
+            agv_status_from_request = (
+                request_data.get("agvStatusList", []) or
+                request_data.get("agvs", [])
+            )
+            
+            self.logger.info(f"鏀跺埌鎵归噺璺緞瑙勫垝璇锋眰锛屽寘鍚┖闂睞GV: {include_idle_agv}, "
+                           f"璇锋眰涓瑼GV鏁伴噺: {len(agv_status_from_request)}, "
+                           f"浣跨敤澧炲己瑙勫垝: {use_enhanced_planning}")
+            
+            agv_status_list = []
+            if agv_status_from_request:
+                self.logger.info("浣跨敤璇锋眰涓彁渚涚殑AGV鐘舵�佹暟鎹繘琛岃矾寰勮鍒�")
+                for agv_data in agv_status_from_request:
+                    try:
+                        agv_status = from_dict(AGVStatus, agv_data)
+                        agv_status_list.append(agv_status)
+                    except Exception as e:
+                        self.logger.warning(f"瑙f瀽璇锋眰涓殑AGV鐘舵�佹暟鎹け璐�: {agv_data} - {e}")
+                        continue
+            else:
+                self.logger.info("浠嶳CS绯荤粺鑾峰彇AGV鐘舵�佹暟鎹繘琛岃矾寰勮鍒�")
+                agv_response = self.rcs_client.get_agv_status()
+                if agv_response.code != ResponseCode.SUCCESS or not agv_response.data:
+                    error_msg = f"鏃犳硶鑾峰彇AGV鐘舵�佽繘琛岃矾寰勮鍒�: {agv_response.msg if agv_response else 'RCS绯荤粺杩炴帴澶辫触'}"
+                    self.logger.error(error_msg)
+                    return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, error_msg)))
+                
+                for agv_data in agv_response.data:
+                    try:
+                        agv_status = from_dict(AGVStatus, agv_data)
+                        agv_status_list.append(agv_status)
+                    except Exception as e:
+                        self.logger.warning(f"瑙f瀽RCS杩斿洖鐨凙GV鐘舵�佹暟鎹け璐�: {agv_data} - {e}")
+                        continue
+            
+            if not agv_status_list:
+                error_msg = "娌℃湁鍙敤鐨凙GV鐘舵�佹暟鎹繘琛岃矾寰勮鍒�"
+                self.logger.error(error_msg)
+                return jsonify(to_dict(create_error_response(ResponseCode.NO_DATA, error_msg)))
+            
+            # 鏇存柊AGV妯″瀷绠$悊鍣�
+            self.agv_manager.update_agv_data(agv_status_list)
+            
+            self.logger.info(f"寮哄埗浣跨敤璺緞瑙勫垝浠ョ‘淇濆寘鍚柊瀛楁")
+            result = self._enhanced_batch_path_planning(agv_status_list, include_idle_agv, constraints)
+            
+            response = create_success_response(result)
+            return jsonify(to_dict(response))
+            
+        except Exception as e:
+            self.logger.error(f"澶勭悊鎵归噺璺緞瑙勫垝璇锋眰澶辫触: {e}", exc_info=True)
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鏈嶅姟鍣ㄩ敊璇�: {str(e)}")))
+    
+    def _enhanced_batch_path_planning(self, agv_status_list: List[AGVStatus], 
+                                    include_idle_agv: bool, 
+                                    constraints: List[Tuple[int, int, float]]) -> Dict[str, Any]:
+        """鎵归噺璺緞瑙勫垝"""
+        from algorithm_system.algorithms.path_planning import PathPlanningFactory
+        
+        # 鍒涘缓鎵归噺璺緞瑙勫垝鍣�
+        batch_planner = PathPlanningFactory.create_batch_path_planner(
+            algorithm_type=self.path_planning_algorithm,
+            path_mapping=self.path_mapping
+        )
+        
+        # 鎵ц鎵归噺璺緞瑙勫垝
+        result = batch_planner.plan_all_agv_paths(
+            agv_status_list=agv_status_list,
+            include_idle_agv=include_idle_agv,
+            constraints=constraints
+        )
+        
+        # 鎻愬彇plannedPaths浣滀负鏈�缁堣繑鍥炴暟鎹�
+        planned_paths = result.get('plannedPaths', [])
+        
+        self.logger.info(f"鎵归噺璺緞瑙勫垝瀹屾垚 - 鎬籄GV: {result['totalAgvs']}, "
+                        f"鎵ц浠诲姟: {result['executingTasksCount']}, "
+                        f"瑙勫垝璺緞: {result['plannedPathsCount']}, "
+                        f"鍐茬獊妫�娴�: {result['conflictsDetected']}, "
+                        f"鎬昏�楁椂: {result['totalPlanningTime']:.2f}ms")
+        
+        # 鍙繑鍥炶矾寰勬暟缁勶紝涓嶅寘鍚叾浠栫粺璁′俊鎭�
+        return planned_paths
+    
+    def _handle_algorithm_config_request(self) -> Dict[str, Any]:
+        """
+        澶勭悊绠楁硶閰嶇疆璇锋眰
+        
+        Returns:
+            Dict: 鍝嶅簲鏁版嵁
+        """
+        try:
+            # 楠岃瘉璇锋眰鏁版嵁
+            if not request.is_json:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "璇锋眰鏁版嵁鏍煎紡閿欒")))
+            
+            config_data = request.get_json()
+            if not config_data:
+                return jsonify(to_dict(create_error_response(ResponseCode.PARAM_EMPTY, "閰嶇疆鏁版嵁涓虹┖")))
+            
+            # 鏇存柊绠楁硶閰嶇疆
+            if "task_allocation_algorithm" in config_data:
+                self.task_allocation_algorithm = config_data["task_allocation_algorithm"]
+                self.logger.info(f"浠诲姟鍒嗛厤绠楁硶鏇存柊涓�: {self.task_allocation_algorithm}")
+            
+            if "path_planning_algorithm" in config_data:
+                self.path_planning_algorithm = config_data["path_planning_algorithm"]
+                self.logger.info(f"璺緞瑙勫垝绠楁硶鏇存柊涓�: {self.path_planning_algorithm}")
+            
+            # 杩斿洖褰撳墠閰嶇疆
+            current_config = {
+                "task_allocation_algorithm": self.task_allocation_algorithm,
+                "path_planning_algorithm": self.path_planning_algorithm
+            }
+            
+            response = create_success_response(current_config)
+            return jsonify(to_dict(response))
+            
+        except Exception as e:
+            self.logger.error(f"澶勭悊绠楁硶閰嶇疆璇锋眰澶辫触: {e}", exc_info=True)
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鏈嶅姟鍣ㄩ敊璇�: {str(e)}")))
+    
+    def _simple_round_robin_allocation(self, tasks: List[TaskData]) -> Dict[str, Any]:
+        """绠�鍗曠殑杞鍒嗛厤"""
+        assignments = []
+        
+        # 灏濊瘯浠嶳CS绯荤粺鑾峰彇AGV鏁伴噺
+        agv_count = 5  # 榛樿鍊�
+        try:
+            agv_response = self.rcs_client.get_agv_status()
+            if agv_response.code == ResponseCode.SUCCESS and agv_response.data:
+                agv_count = len(agv_response.data)
+                self.logger.info(f"浠嶳CS绯荤粺鑾峰彇鍒癆GV鏁伴噺: {agv_count}")
+            else:
+                # 濡傛灉RCS杩斿洖鏃犳暟鎹紝浣跨敤閰嶇疆鐨勯粯璁ゅ��
+                from config.settings import DEFAULT_AGV_COUNT
+                agv_count = DEFAULT_AGV_COUNT
+                self.logger.warning(f"鏃犳硶浠嶳CS鑾峰彇AGV鏁伴噺锛屼娇鐢ㄩ粯璁ゅ��: {agv_count}")
+        except Exception as e:
+            # 濡傛灉瀹屽叏鏃犳硶杩炴帴RCS锛屼娇鐢ㄩ厤缃殑榛樿鍊�
+            from config.settings import DEFAULT_AGV_COUNT
+            agv_count = DEFAULT_AGV_COUNT
+            self.logger.error(f"鑾峰彇AGV鏁伴噺澶辫触锛屼娇鐢ㄩ粯璁ゅ��: {agv_count} - {e}")
+        
+        for i, task in enumerate(tasks):
+            agv_id = f"AGV_{10001 + (i % agv_count)}"
+            assignment = TaskAssignment(
+                taskId=task.taskId,
+                agvId=agv_id
+            )
+            assignments.append(assignment)
+        
+        assignment_data = [to_dict(assignment) for assignment in assignments]
+        
+        self.logger.info(f"浣跨敤绠�鍗曡疆璇㈠垎閰嶄簡 {len(assignments)} 涓换鍔★紝AGV鏁伴噺: {agv_count}")
+        
+        response = create_success_response(assignment_data)
+        return jsonify(to_dict(response))
+    
+    def _handle_start_path_monitor_request(self) -> Dict[str, Any]:
+        """澶勭悊鍚姩璺緞鐩戞帶鏈嶅姟璇锋眰"""
+        try:
+            if not self.path_monitor:
+                return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, "璺緞鐩戞帶鏈嶅姟鏈垵濮嬪寲")))
+            
+            if self.path_monitor.is_running:
+                return jsonify(to_dict(create_success_response({"message": "璺緞鐩戞帶鏈嶅姟宸插湪杩愯涓�"})))
+            
+            # 鍚姩璺緞鐩戞帶鏈嶅姟
+            self.path_monitor.start_monitoring()
+            
+            self.logger.info("璺緞鐩戞帶鏈嶅姟宸查�氳繃API鍚姩")
+            
+            response = create_success_response({
+                "message": "璺緞鐩戞帶鏈嶅姟鍚姩鎴愬姛",
+                "monitor_status": self.path_monitor.get_monitoring_status()
+            })
+            
+            return jsonify(to_dict(response))
+            
+        except Exception as e:
+            self.logger.error(f"鍚姩璺緞鐩戞帶鏈嶅姟澶辫触: {e}")
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鍚姩璺緞鐩戞帶鏈嶅姟澶辫触: {str(e)}")))
+    
+    def _handle_stop_path_monitor_request(self) -> Dict[str, Any]:
+        """澶勭悊鍋滄璺緞鐩戞帶鏈嶅姟璇锋眰"""
+        try:
+            if not self.path_monitor:
+                return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, "璺緞鐩戞帶鏈嶅姟鏈垵濮嬪寲")))
+            
+            if not self.path_monitor.is_running:
+                return jsonify(to_dict(create_success_response({"message": "璺緞鐩戞帶鏈嶅姟鏈湪杩愯"})))
+            
+            # 鍋滄璺緞鐩戞帶鏈嶅姟
+            self.path_monitor.stop_monitoring()
+            
+            self.logger.info("璺緞鐩戞帶鏈嶅姟宸查�氳繃API鍋滄")
+            
+            response = create_success_response({
+                "message": "璺緞鐩戞帶鏈嶅姟鍋滄鎴愬姛",
+                "monitor_status": self.path_monitor.get_monitoring_status()
+            })
+            
+            return jsonify(to_dict(response))
+            
+        except Exception as e:
+            self.logger.error(f"鍋滄璺緞鐩戞帶鏈嶅姟澶辫触: {e}")
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鍋滄璺緞鐩戞帶鏈嶅姟澶辫触: {str(e)}")))
+    
+    def _handle_path_monitor_status_request(self) -> Dict[str, Any]:
+        """澶勭悊璺緞鐩戞帶鏈嶅姟鐘舵�佹煡璇㈣姹�"""
+        try:
+            if not self.path_monitor:
+                return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, "璺緞鐩戞帶鏈嶅姟鏈垵濮嬪寲")))
+            
+            monitor_status = self.path_monitor.get_monitoring_status()
+            
+            response = create_success_response({
+                "monitor_status": monitor_status,
+                "description": "璺緞鐩戞帶鏈嶅姟鐘舵�佷俊鎭�"
+            })
+            
+            return jsonify(to_dict(response))
+            
+        except Exception as e:
+            self.logger.error(f"鑾峰彇璺緞鐩戞帶鏈嶅姟鐘舵�佸け璐�: {e}")
+            return jsonify(to_dict(create_error_response(ResponseCode.SERVER_ERROR, f"鑾峰彇璺緞鐩戞帶鏈嶅姟鐘舵�佸け璐�: {str(e)}")))
+    
+    def start_server(self):
+        """鍚姩绠楁硶鏈嶅姟鍣�"""
+        self.logger.info(f"鍚姩绠楁硶绯荤粺鏈嶅姟鍣�: http://{self.host}:{self.port}")
+        
+        try:
+            # 濡傛灉鍚敤浜嗚矾寰勭洃鎺ф湇鍔★紝鑷姩鍚姩
+            if self.path_monitor and self.enable_path_monitor:
+                self.path_monitor.start_monitoring()
+                self.logger.info("璺緞鐩戞帶鏈嶅姟宸茶嚜鍔ㄥ惎鍔�")
+            
+            self.app.run(
+                host=self.host,
+                port=self.port,
+                debug=False,
+                threaded=True
+            )
+        except Exception as e:
+            self.logger.error(f"鍚姩绠楁硶鏈嶅姟鍣ㄥけ璐�: {e}")
+            # 纭繚鍦ㄥ惎鍔ㄥけ璐ユ椂鍋滄璺緞鐩戞帶鏈嶅姟
+            if self.path_monitor and self.path_monitor.is_running:
+                self.path_monitor.stop_monitoring()
+            raise
+    
+    def stop_server(self):
+        """鍋滄绠楁硶鏈嶅姟鍣�"""
+        self.logger.info("鍋滄绠楁硶鏈嶅姟鍣�")
+        
+        # 鍋滄璺緞鐩戞帶鏈嶅姟
+        if self.path_monitor and self.path_monitor.is_running:
+            self.path_monitor.stop_monitoring()
+            self.logger.info("璺緞鐩戞帶鏈嶅姟宸插仠姝�")
+
+    
+    def get_server_status(self) -> Dict[str, Any]:
+        """鑾峰彇鏈嶅姟鍣ㄧ姸鎬�"""
+        monitor_status = None
+        if self.path_monitor:
+            monitor_status = self.path_monitor.get_monitoring_status()
+        
+        return {
+            "host": self.host,
+            "port": self.port,
+            "path_mapping_loaded": len(self.path_mapping) > 0,
+            "agv_count": len(self.agv_manager.get_all_agvs()),
+            "algorithms": {
+                "task_allocation": self.task_allocation_algorithm,
+                "path_planning": self.path_planning_algorithm
+            },
+            "path_monitor": monitor_status,
+            "timestamp": time.time()
+        } 
\ No newline at end of file

--
Gitblit v1.9.1