# Tellme PDMS 插件技术架构文档 ## 1. 项目概述 - **目标**:为单个 AVEVA PDMS 12.1 SP4 会话提供远程监控与操作能力,实现前端客户端通过 HTTP 接口安全地获取模型状态并下达任务。 - **运行环境**:.NET Framework 3.5(x86),遵循 PDMS 插件加载约束;前端与插件运行在同一主机,通信默认局限于本地回环接口。 - **核心原则**:主线程执行 PDMS API、命令模式分离网络与业务、无硬编码数据、兼顾大模型性能与资源占用。 ## 2. 系统总体架构 ```mermaid graph LR A[前端客户端] -->|HTTP/JSON| B[HttpServer] B -->|入队| C[SafeQueue] C -->|出队| D[PDMS 主线程] D --> E[Aveva PDMS API] D -->|结果| B B -->|响应| A ``` - **入口插件 (`TellmePdmsAddin`)**:实现 `IAddin` 接口,在 PDMS 启动时加载,负责生命周期管理和日志记录。 - **网络层 (`Network.HttpServer`)**:基于 `System.Net.HttpListener` 自托管 HTTP 服务,路由健康检查与业务接口。 - **命令层 (`Core.ICommand` 系列)**:每个请求解析为命令对象入队,支持可取消性扩展。 - **业务层 (`Core.PdmsManager`)**:封装对 `MDB.CurrentMDB`、`Project.CurrentProject`、`DbElement` 等 API 的访问,生成结构化数据。 - **模型层 (`Models.*`)**:定义 `ModelStatusResponse`、`ProjectInfo`、`ModelStatistics`、`SessionInfo` 等 DTO 以便序列化。 - **工具层**:提供线程安全队列、日志、序列化和配置扩展点(`Utils` 目录预留)。 ## 3. 关键技术栈 | 分类 | 选型 | 理由 | | --- | --- | --- | | 插件框架 | `Aveva.ApplicationFramework.IAddin` | 满足 PDMS 扩展规范,允许在主线程注册 Idle 事件 | | 语言与平台 | C# + .NET Framework 3.5 (x86) | 与 PDMS 12.1 SP4 兼容,仅 32 位可加载 | | 网络通信 | `System.Net.HttpListener` | BCL 自带、无第三方依赖、支持本地自托管 | | 序列化 | 自定义轻量 JSON 序列化 | 兼容 .NET 3.5,避免外部依赖,可替换为 `System.Web.Script.Serialization` | | 队列实现 | `Queue` + `lock` 封装 | .NET 3.5 无 `ConcurrentQueue`,需手动保证线程安全 | | 日志 | 文本文件 (`C:\temp\*.txt`) | 易于部署与排查,可替换为 log4net | | 单元测试(预留) | NUnit 2.x | 支持 .NET 3.5,便于未来补充测试 | ## 4. 主要模块说明 ### 4.1 插件入口 `TellmePdmsAddin` - `Start(ServiceManager)`:初始化 `HttpServer`、记录启动日志、提示监听端口,并可在此处加载配置或注册 UI 菜单。 - `Stop()`:释放服务器资源并记录停止日志。 - `Application.Idle` 事件在其他模块注册,用于在 PDMS 主线程执行命令队列。 ### 4.2 网络服务 `Network.HttpServer` - 构造函数注入端口(默认 9001),仅允许 `http://localhost:/`。 - `Start()`/`Stop()` 控制 `HttpListener` 生命周期,利用 `BeginGetContext` 异步接受请求。 - `ProcessRequest` 完成路由分发、CORS 头设置、异常捕获与响应写入。 - 当前实现的路由:`/health`、`/test`、`/api/status/model`,可扩展 `switch` 和命令解析以支持更多端点。 ### 4.3 命令抽象 `Core.ICommand` - 统一定义 `CommandId`、`CommandType`、`Execute()`,保留 `CanCancel/Cancel()` 扩展位。 - 推荐为每个 HTTP 接口实现对应命令类,确保执行逻辑仅运行在主线程环境。 ### 4.4 业务管理 `Core.PdmsManager` - 单例模式管理 PDMS 状态查询,避免重复初始化。 - `GetModelStatus()`:集中调度连接检测、项目信息、模型统计、会话信息。 - **连接检测**:`MDB.CurrentMDB` 是否返回非空。 - **项目信息**:通过 `CurrentMDB.GetFirstDB(DbType.Design)` 获取设计库名称、MDS 名称、PDMS 版本。 - **模型统计**:递归 `DbElement.Members()`,使用 `element.GetActualType().Name` 累加 SITE、ZONE、PIPE 等关键元素数量。 - **Zone 统计**:遍历 SITE → ZONE 层级,利用 `DbElement.GetValidString(DbAttributeInstance.NAME, ref zoneName)` 采集激活区域名称。 - **会话信息**:从 `DesignDb.CurrentSession` 读取用户、启动时间,计算持续分钟数。 - 所有 API 调用包裹 try/catch 并输出调试日志以保证稳定性。 ## 5. 线程模型 - HttpListener 线程仅负责解析请求并将命令入队,禁止直接调用 PDMS API。 - 主线程通过 `Application.Idle` 循环 `SafeQueue.TryDequeue(out ICommand cmd)`,顺序执行。 - 可在命令执行过程中更新共享的进度字典,以供 `/task/{id}` 查询(待实现)。 - 长任务需在执行逻辑内部分批处理,并在批次间调用 `GC.Collect()` 控制内存。 ## 6. HTTP 接口约定 | 路径 | 方法 | 描述 | 响应示例 | | --- | --- | --- | --- | | `/health` | GET | 进程存活检测,返回时间戳与内存占用 | `{ "code":0, "message":"成功", "data":{ "status":"OK", "timestamp":"2025-09-21 12:00:00", "memoryMB":123 } }` | | `/test` | GET | 轻量连通性测试,检测是否运行于 PDMS 环境 | `{ "success":true, "data":{ "running":true, "message":"TellmePdms 与 PDMS 连接正常" }, "error":null }` | | `/api/status/model` | GET | 返回模型加载状态、项目信息、元素统计、会话信息 | `{ "code":0, "message":"成功", "data":{ ...ModelStatusResponse... } }` | - 响应以 `ApiResponse` 模式封装:`code` 为 0 表示成功,`message` 给出提示,`data` 为业务数据。 - 自定义错误码示例:`1001` 表示 PDMS 模型未加载,`500` 表示内部异常。 - 未来规划接口:`POST /command`、`POST /task`、`GET /task/{id}`、`GET /stats`、`POST /export/ifc` 等,可复用命令与模型层。 ## 7. 数据模型结构 ### 7.1 `ModelStatusResponse` - `ModelLoaded`:PDMS 是否加载模型。 - `ProjectInfo`:包含 `ProjectName`、`MdsName`、`PdmsVersion`。 - `ModelStatistics`:`TotalElements`、`ElementCounts (Dictionary)`、`ZoneCount`、`ActiveZones`。 - `SessionInfo`:会话 `UserName`、`StartTime`、`DurationMinutes`。 ### 7.2 序列化策略 - 对字典、列表使用定制序列化,确保 .NET 3.5 环境兼容。 - 日期统一格式 `yyyy-MM-ddTHH:mm:ssZ`,便于前端解析。 - 主线程执行结束后返回 JSON 字符串,由 HttpServer 写入响应流。 ## 8. 性能与资源控制 - **Large Address Aware**:建议为 32 位进程设置 LAA 标志,在 64 位 Windows 上提升可用内存上限至 3 GB。 - **分批遍历**:对大模型递归时,可按逻辑域(SITE、ZONE)分批处理,减少单次内存占用。 - **流式响应**:长列表数据可拆分分页或使用压缩(GZip + Base64)后流式传输,避免一次性加载。 - **GC 管理**:在长任务各阶段主动调用 `GC.Collect()` 并输出当前内存占用,防止内存峰值。 - **并发限制**:当前设计为单客户端单任务,无任务队列优先级;后续可引入任务管理表实现调度与取消。 ## 9. 日志与错误处理 - 插件与服务器分别记录至 `C:\temp\pdms_plugin_log.txt`、`C:\temp\pdms_http_log.txt`。 - 网络层捕获异常后返回 500 错误并写入日志;业务层捕获异常后返回自定义错误码。 - 建议引入滚动日志策略(log4net RollingFileAppender)以限制文件大小。 ## 10. 部署与配置 1. 以 x86、.NET 3.5 配置编译 `TellmePdmsPluging.sln`。 2. 将输出 DLL 复制到 PDMS 安装目录,更新 `DesignAddin.xml` 注册插件。 3. 确保 Windows 防火墙允许本地回环端口 9001;外部访问需额外代理。 4. 可在 `Config` 目录引入自定义配置(端口、日志路径、批处理大小等),启动时读取。 5. 部署后通过 `http://localhost:9001/health` 验证服务是否监听。 ## 11. 后续扩展建议 - **任务管理**:实现 `/task` 接口与任务表持久化,支持长任务进度查询与取消。 - **安全加固**:加入鉴权(如基于令牌或双向证书),限制访问来源。 - **前端工具**:提供 Web 或桌面客户端,集成状态展示与命令触发。 - **协议升级**:考虑使用 WebSocket 推送进度、MessagePack/Protobuf 提升带宽效率。 - **监控告警**:将健康检查与日志集成到企业监控平台,追踪内存与任务状态。 --- 本文件概述了 Tellme PDMS 远程控制插件的架构设计、核心组件、关键算法与部署要点,可作为后续开发迭代、测试验证及运维交付的基础参考资料。