using System; using System.Net; using System.Text; using System.IO; using System.Collections.Generic; using System.Web.Script.Serialization; using TellmePdmsPluging.Commands; using TellmePdmsPluging.Core; using TellmePdmsPluging.Models; namespace TellmePdmsPluging.Network { public class HttpServer : IDisposable { private readonly HttpListener _listener; private readonly BatchTaskResultCallbackService _batchCallbackService; private readonly int _port; private bool _isRunning; public HttpServer(int port = 9001) { _port = port; _listener = new HttpListener(); _listener.Prefixes.Add($"http://localhost:{port}/"); _batchCallbackService = new BatchTaskResultCallbackService( Environment.GetEnvironmentVariable("TELLME_BATCH_CALLBACK_SERVER"), Environment.GetEnvironmentVariable("TELLME_BATCH_CALLBACK_TOKEN"), "pdms"); } public void Start() { try { _listener.Start(); _isRunning = true; // 开始异步监听请求 _listener.BeginGetContext(OnHttpRequest, null); LogMessage($"HTTP服务器已启动,监听端口: {_port}"); } catch (Exception ex) { LogMessage($"HTTP服务器启动失败: {ex.Message}"); throw; } } public void Stop() { try { _isRunning = false; _listener?.Stop(); LogMessage("HTTP服务器已停止"); } catch (Exception ex) { LogMessage($"HTTP服务器停止时出错: {ex.Message}"); } } private void OnHttpRequest(IAsyncResult result) { if (!_isRunning) return; try { var context = _listener.EndGetContext(result); // 继续监听下一个请求 _listener.BeginGetContext(OnHttpRequest, null); // 处理当前请求 ProcessRequest(context); } catch (Exception ex) { LogMessage($"处理HTTP请求时出错: {ex.Message}"); // 如果服务器仍在运行,继续监听 if (_isRunning) { try { _listener.BeginGetContext(OnHttpRequest, null); } catch { } } } } private void ProcessRequest(HttpListenerContext context) { try { var request = context.Request; var response = context.Response; // 设置响应头 response.ContentType = "application/json; charset=utf-8"; response.Headers.Add("Access-Control-Allow-Origin", "*"); response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); response.Headers.Add("Access-Control-Allow-Headers", "Content-Type"); string responseJson; // 处理OPTIONS预检请求 if (request.HttpMethod == "OPTIONS") { response.StatusCode = 200; response.Close(); return; } // 路由处理 string path = request.Url.AbsolutePath.ToLower(); switch (path) { case "/health": responseJson = HandleHealthCheck(); break; case "/test": responseJson = HandleTest(); break; case "/api/status/model": responseJson = HandleModelStatus(); break; case "/api/project/open": responseJson = HandleProjectOpen(request); break; case "/api/project/close": responseJson = HandleProjectClose(request); break; case "/api/mdb/open": responseJson = HandleMdbOpen(request); break; case "/api/model/simplify": responseJson = HandleModelSimplify(request); break; case "/api/model/shrinkwrap": responseJson = HandleModelShrinkwrap(request); break; case "/api/export/ifc": responseJson = HandleExportIfc(request); break; default: response.StatusCode = 404; responseJson = CreateErrorResponse(404, "接口不存在"); break; } // 发送响应 byte[] buffer = Encoding.UTF8.GetBytes(responseJson); response.ContentLength64 = buffer.Length; response.OutputStream.Write(buffer, 0, buffer.Length); response.Close(); LogMessage($"{request.HttpMethod} {path} - {response.StatusCode}"); } catch (Exception ex) { LogMessage($"处理请求时出错: {ex.Message}"); try { context.Response.StatusCode = 500; string errorJson = CreateErrorResponse(500, "服务器内部错误"); byte[] errorBuffer = Encoding.UTF8.GetBytes(errorJson); context.Response.OutputStream.Write(errorBuffer, 0, errorBuffer.Length); context.Response.Close(); } catch { } } } private string HandleHealthCheck() { try { var healthData = new { status = "OK", timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), memoryMB = GC.GetTotalMemory(false) / 1024 / 1024 }; return CreateSuccessResponse(healthData); } catch (Exception ex) { return CreateErrorResponse(500, $"健康检查失败: {ex.Message}"); } } private string HandleTest() { try { // 检查PDMS应用程序状态 bool pdmsRunning = CheckPdmsStatus(); var testData = new { running = pdmsRunning, message = pdmsRunning ? "TellmePdms 与 PDMS 连接正常" : "PDMS 未运行或连接异常" }; // 使用新的响应格式 return CreateTestResponse(true, testData, null); } catch (Exception ex) { return CreateTestResponse(false, null, ex.Message); } } private string HandleModelStatus() { try { var modelStatus = PdmsManager.Instance.GetModelStatus(); if (!modelStatus.ModelLoaded) { return CreateErrorResponse(1001, "PDMS模型未加载"); } return CreateSuccessResponse(modelStatus); } catch (Exception ex) { LogMessage($"获取模型状态失败: {ex.Message}"); return CreateErrorResponse(500, $"获取模型状态失败: {ex.Message}"); } } private string HandleModelSimplify(HttpListenerRequest request) { string executionId = null; try { var payload = ReadRequestBody(request); if (string.IsNullOrEmpty(payload)) { return CreateErrorResponse(400, "请求体不能为空"); } var serializer = new JavaScriptSerializer(); var simplifyRequest = serializer.Deserialize(payload) ?? new SimplifyModelRequest(); executionId = simplifyRequest.ExecutionId; var command = new SimplifyModelCommand(simplifyRequest); var invokeResult = MainThreadInvoker.Invoke(command, 600000); if (!invokeResult.Success) { var msg = string.IsNullOrEmpty(invokeResult.Message) ? "模型轻量化失败" : invokeResult.Message; NotifyBatchTaskResult(simplifyRequest.ExecutionId, false, msg, null); return CreateErrorResponse(500, msg); } var result = invokeResult.Result as SimplifyModelResult; if (result == null) { return CreateErrorResponse(500, "模型轻量化结果为空"); } if (!result.Success) { var message = string.IsNullOrEmpty(result.Message) ? "模型轻量化失败" : result.Message; NotifyBatchTaskResult(simplifyRequest.ExecutionId, false, message, null); return CreateErrorResponse(500, message); } NotifyBatchTaskResult(simplifyRequest.ExecutionId, true, null, result); return CreateSuccessResponse(result); } catch (Exception ex) { NotifyBatchTaskResult(executionId, false, ex.Message, null); return CreateErrorResponse(500, $"模型轻量化失败: {ex.Message}"); } } private string HandleModelShrinkwrap(HttpListenerRequest request) { string executionId = null; try { if (!string.Equals(request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase)) { return CreateErrorResponse(405, "仅支持POST"); } var payload = ReadRequestBody(request); if (string.IsNullOrEmpty(payload)) { return CreateErrorResponse(400, "请求体不能为空"); } var serializer = new JavaScriptSerializer(); var shrinkwrapRequest = serializer.Deserialize(payload) ?? new ShrinkwrapModelRequest(); executionId = shrinkwrapRequest.ExecutionId; var command = new ShrinkwrapModelCommand(shrinkwrapRequest); // executionId 场景采用异步提交,避免长时间阻塞HTTP连接。 if (!string.IsNullOrEmpty(shrinkwrapRequest.ExecutionId)) { MainThreadInvoker.InvokeAsync(command, asyncInvokeResult => { try { if (!asyncInvokeResult.Success) { var msg = string.IsNullOrEmpty(asyncInvokeResult.Message) ? "外壳保留失败" : asyncInvokeResult.Message; NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, false, msg, null); return; } var asyncResult = asyncInvokeResult.Result as ShrinkwrapModelResult; if (asyncResult == null) { NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, false, "外壳保留结果为空", null); return; } if (!asyncResult.Success) { var message = string.IsNullOrEmpty(asyncResult.Message) ? "外壳保留失败" : asyncResult.Message; NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, false, message, null); return; } NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, true, null, asyncResult); } catch (Exception callbackEx) { NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, false, callbackEx.Message, null); } }); var acceptedData = new { accepted = true, executionId = shrinkwrapRequest.ExecutionId, status = "QUEUED", message = "外壳保留任务已提交" }; return CreateSuccessResponse(acceptedData); } var invokeResult = MainThreadInvoker.Invoke(command, 600000); if (!invokeResult.Success) { var msg = string.IsNullOrEmpty(invokeResult.Message) ? "外壳保留失败" : invokeResult.Message; NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, false, msg, null); return CreateErrorResponse(500, msg); } var result = invokeResult.Result as ShrinkwrapModelResult; if (result == null) { return CreateErrorResponse(500, "外壳保留结果为空"); } if (!result.Success) { var message = string.IsNullOrEmpty(result.Message) ? "外壳保留失败" : result.Message; NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, false, message, null); return CreateErrorResponse(500, message); } NotifyBatchTaskResult(shrinkwrapRequest.ExecutionId, true, null, result); return CreateSuccessResponse(result); } catch (Exception ex) { NotifyBatchTaskResult(executionId, false, ex.Message, null); return CreateErrorResponse(500, $"外壳保留失败: {ex.Message}"); } } private string HandleProjectOpen(HttpListenerRequest request) { string executionId = null; try { if (!string.Equals(request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase)) { return CreateErrorResponse(405, "仅支持POST"); } var payload = ReadRequestBody(request); if (string.IsNullOrEmpty(payload)) { return CreateErrorResponse(400, "请求体不能为空"); } var serializer = new JavaScriptSerializer(); var openRequest = serializer.Deserialize(payload) ?? new OpenProjectRequest(); executionId = openRequest.ExecutionId; var command = new OpenProjectCommand(openRequest); var invokeResult = MainThreadInvoker.Invoke(command, 600000); if (!invokeResult.Success) { var msg = string.IsNullOrEmpty(invokeResult.Message) ? "打开项目失败" : invokeResult.Message; NotifyBatchTaskResult(openRequest.ExecutionId, false, msg, null); return CreateErrorResponse(500, msg); } var result = invokeResult.Result as OpenProjectResult; if (result == null) { return CreateErrorResponse(500, "打开项目结果为空"); } if (!result.Success) { var message = string.IsNullOrEmpty(result.Message) ? "打开项目失败" : result.Message; NotifyBatchTaskResult(openRequest.ExecutionId, false, message, null); return CreateErrorResponse(500, message); } NotifyBatchTaskResult(openRequest.ExecutionId, true, null, result); return CreateSuccessResponse(result); } catch (Exception ex) { NotifyBatchTaskResult(executionId, false, ex.Message, null); return CreateErrorResponse(500, $"打开项目失败: {ex.Message}"); } } private string HandleProjectClose(HttpListenerRequest request) { string executionId = null; try { if (!string.Equals(request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase)) { return CreateErrorResponse(405, "仅支持POST"); } var payload = ReadRequestBody(request); var serializer = new JavaScriptSerializer(); var closeRequest = string.IsNullOrEmpty(payload) ? new CloseProjectRequest() : (serializer.Deserialize(payload) ?? new CloseProjectRequest()); executionId = closeRequest.ExecutionId; var command = new CloseProjectCommand(closeRequest); var invokeResult = MainThreadInvoker.Invoke(command, 600000); if (!invokeResult.Success) { var msg = string.IsNullOrEmpty(invokeResult.Message) ? "关闭项目失败" : invokeResult.Message; NotifyBatchTaskResult(closeRequest.ExecutionId, false, msg, null); return CreateErrorResponse(500, msg); } var result = invokeResult.Result as CloseProjectResult; if (result == null) { return CreateErrorResponse(500, "关闭项目结果为空"); } if (!result.Success) { var message = string.IsNullOrEmpty(result.Message) ? "关闭项目失败" : result.Message; NotifyBatchTaskResult(closeRequest.ExecutionId, false, message, null); return CreateErrorResponse(500, message); } NotifyBatchTaskResult(closeRequest.ExecutionId, true, null, result); return CreateSuccessResponse(result); } catch (Exception ex) { NotifyBatchTaskResult(executionId, false, ex.Message, null); return CreateErrorResponse(500, "关闭项目失败: " + ex.Message); } } private string HandleMdbOpen(HttpListenerRequest request) { string executionId = null; try { if (!string.Equals(request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase)) { return CreateErrorResponse(405, "仅支持POST"); } var payload = ReadRequestBody(request); if (string.IsNullOrEmpty(payload)) { return CreateErrorResponse(400, "请求体不能为空"); } var serializer = new JavaScriptSerializer(); var openRequest = serializer.Deserialize(payload) ?? new OpenMdbRequest(); executionId = openRequest.ExecutionId; var command = new OpenMdbCommand(openRequest); var invokeResult = MainThreadInvoker.Invoke(command, 600000); if (!invokeResult.Success) { var msg = string.IsNullOrEmpty(invokeResult.Message) ? "打开MDB失败" : invokeResult.Message; NotifyBatchTaskResult(openRequest.ExecutionId, false, msg, null); return CreateErrorResponse(500, msg); } var result = invokeResult.Result as OpenMdbResult; if (result == null) { return CreateErrorResponse(500, "打开MDB结果为空"); } if (!result.Success) { var message = string.IsNullOrEmpty(result.Message) ? "打开MDB失败" : result.Message; NotifyBatchTaskResult(openRequest.ExecutionId, false, message, null); return CreateErrorResponse(500, message); } NotifyBatchTaskResult(openRequest.ExecutionId, true, null, result); return CreateSuccessResponse(result); } catch (Exception ex) { NotifyBatchTaskResult(executionId, false, ex.Message, null); return CreateErrorResponse(500, $"打开MDB失败: {ex.Message}"); } } private string HandleExportIfc(HttpListenerRequest request) { string executionId = null; try { if (!string.Equals(request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase)) { return CreateErrorResponse(405, "仅支持POST"); } var payload = ReadRequestBody(request); if (string.IsNullOrEmpty(payload)) { return CreateErrorResponse(400, "请求体不能为空"); } var serializer = new JavaScriptSerializer(); var exportRequest = serializer.Deserialize(payload) ?? new ExportIfcRequest(); executionId = exportRequest.ExecutionId; var command = new ExportIfcCommand(exportRequest); var invokeResult = MainThreadInvoker.Invoke(command, 600000); if (!invokeResult.Success) { var msg = string.IsNullOrEmpty(invokeResult.Message) ? "RVM导出失败" : invokeResult.Message; NotifyBatchTaskResult(exportRequest.ExecutionId, false, msg, null); return CreateErrorResponse(500, msg); } var result = invokeResult.Result as ExportIfcResult; if (result == null) { return CreateErrorResponse(500, "RVM导出结果为空"); } if (!result.Success) { var message = string.IsNullOrEmpty(result.Message) ? "RVM导出失败" : result.Message; NotifyBatchTaskResult(exportRequest.ExecutionId, false, message, null); return CreateErrorResponse(500, message); } NotifyBatchTaskResult(exportRequest.ExecutionId, true, null, result); return CreateSuccessResponse(result); } catch (Exception ex) { NotifyBatchTaskResult(executionId, false, ex.Message, null); return CreateErrorResponse(500, $"RVM导出失败: {ex.Message}"); } } private string ReadRequestBody(HttpListenerRequest request) { if (request == null || request.InputStream == null) { return string.Empty; } using (var reader = new StreamReader(request.InputStream, request.ContentEncoding ?? Encoding.UTF8)) { return reader.ReadToEnd(); } } private bool CheckPdmsStatus() { try { // 检查是否在PDMS环境中运行 var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in loadedAssemblies) { if (assembly.FullName.Contains("Aveva.ApplicationFramework") || assembly.FullName.Contains("PMLNet")) { return true; } } return false; } catch { return false; } } private string CreateTestResponse(bool success, object data, string error) { // 手动构建JSON以确保格式正确 string dataJson = "null"; if (data != null) { dataJson = SimpleJsonSerialize(data); } string errorJson = error == null ? "null" : $"\"{error}\""; return $"{{\"success\":{success.ToString().ToLower()},\"data\":{dataJson},\"error\":{errorJson}}}"; } private string CreateSuccessResponse(object data) { return $"{{\"code\":0,\"message\":\"成功\",\"data\":{SimpleJsonSerialize(data)}}}"; } private string CreateErrorResponse(int code, string message) { return $"{{\"code\":{code},\"message\":\"{message}\",\"data\":null}}"; } private string SimpleJsonSerialize(object obj) { if (obj == null) return "null"; // 检查是否为ModelStatusResponse类型 if (obj is ModelStatusResponse) { return SerializeModelStatusResponse((ModelStatusResponse)obj); } // 检查基本类型 if (obj is string) return $"\"{obj}\""; if (obj is bool) return obj.ToString().ToLower(); if (obj is DateTime) return $"\"{((DateTime)obj).ToString("yyyy-MM-ddTHH:mm:ssZ")}\""; if (obj.GetType().IsPrimitive) return obj.ToString(); // 检查集合类型 if (obj is Dictionary) { var dict = (Dictionary)obj; var dictParts = new List(); foreach (var kvp in dict) { dictParts.Add($"\"{kvp.Key}\":{kvp.Value}"); } return "{" + string.Join(",", dictParts.ToArray()) + "}"; } if (obj is List) { var list = (List)obj; var listParts = new List(); foreach (var item in list) { listParts.Add($"\"{item}\""); } return "[" + string.Join(",", listParts.ToArray()) + "]"; } if (obj is double[]) { var array = (double[])obj; var arrayParts = new List(); foreach (var item in array) { arrayParts.Add(item.ToString()); } return "[" + string.Join(",", arrayParts.ToArray()) + "]"; } // 普通对象序列化 var properties = obj.GetType().GetProperties(); var jsonParts = new List(); foreach (var prop in properties) { var value = prop.GetValue(obj, null); string jsonValue = SimpleJsonSerialize(value); jsonParts.Add($"\"{prop.Name}\":{jsonValue}"); } return "{" + string.Join(",", jsonParts.ToArray()) + "}"; } private string SerializeModelStatusResponse(ModelStatusResponse model) { var parts = new List(); parts.Add($"\"ModelLoaded\":{model.ModelLoaded.ToString().ToLower()}"); parts.Add($"\"ProjectInfo\":{SimpleJsonSerialize(model.ProjectInfo)}"); parts.Add($"\"ModelStatistics\":{SimpleJsonSerialize(model.ModelStatistics)}"); parts.Add($"\"SessionInfo\":{SimpleJsonSerialize(model.SessionInfo)}"); parts.Add($"\"ExportDiagnostics\":{SimpleJsonSerialize(model.ExportDiagnostics)}"); return "{" + string.Join(",", parts.ToArray()) + "}"; } private void NotifyBatchTaskResult(string executionId, bool success, string errorMessage, object result) { _batchCallbackService.NotifyTaskResultAsync(executionId, success, errorMessage, result); } private void LogMessage(string message) { try { string logPath = @"C:\temp\pdms_http_log.txt"; string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}\r\n"; File.AppendAllText(logPath, logEntry); } catch { } } public void Dispose() { Stop(); _listener?.Close(); } } }