RTU_ALL_AI/docs/system/libweb_server/PLC_CONFIG_SPEC.md

12 KiB
Raw Permalink Blame History

PLC 配置页面原始功能详细规格

基于原工程 libplc C 引擎 + Reclose_logic.xml 完整分析 分析日期: 2026-07-10 目标: 重构前端 PLC Config 页面,做到比原工程更好


一、PLC 系统架构

┌─────────────────────────────────────────────────────────────────┐
│                     RTU 运行时                                    │
│                                                                  │
│  config/PLC/Reclose_logic.xml ──→ pls.cpp parse_reclose_logic   │
│  (mtime 文件变化检测, stat)          │                            │
│                                     ↓                            │
│                              LogicGraph[] (最多4个)               │
│                                     │                            │
│                              EV_TIMER3 (1s)                      │
│                                     ↓                            │
│                              PLC_Logic() 执行:                   │
│                              1. 读取 datacenter input 信号        │
│                              2. Kahn 拓扑排序                    │
│                              3. 按拓扑序执行各门逻辑               │
│                              4. 写入 datacenter output 信号       │
└─────────────────────────────────────────────────────────────────┘

二、XML 格式完全规格 (Reclose_logic.xml)

顶层结构

<?xml version="1.0" encoding="UTF-8"?>
<PLCConfig name="PLC Logic" key="1783070862205" checksum="3486BE04">
    <Chain gates="N" inputs="N" outputs="N">
        <!-- 简单 Chain 无 Comb: Inputs → Gates → Outputs 顺序 -->
        <Inputs>   <Signal no="ID" x="X" y="Y"/> ... </Inputs>
        <Gate type="TYPE" id="N" x="X" y="Y" [delayMs="MS"] [S="src"] [R="src"]/>
        ...
        <!-- 含 Comb 的 Chain: Comb 可嵌套, 位置不固定 -->
        <Comb id="N">
            <Inputs> ... </Inputs>
            <Gate .../>
            <Comb id="N">  <!-- 嵌套 Comb -->
                <Inputs> ... </Inputs>
                <Gate .../>
                <Outputs> ... </Outputs>
            </Comb>
            <Gate .../>
            <Outputs> ... </Outputs>
        </Comb>
        <Outputs>  <Signal no="ID" x="X" y="Y"/> ... </Outputs>
    </Chain>
    <Chain ...> ... </Chain>
</PLCConfig>

关键节点类型 (10 种)

type Name 功能 参数 输入引脚 输出引脚
0 INPUT 硬件输入, 从 datacenter 读取值 no=信号ID 0 1
1 OUTPUT 硬件输出, 写入 datacenter no=信号ID 1 0
2 OR 或门, 任意输入=1→输出1 id=门ID 2 1
3 AND 与门, 全部输入=1→输出1 id=门ID 2 1
4 NOT 非门, 取反 id=门ID 1 1
5 T62P 延时导通 (IN=1 等待 delayMs ms 后 OUT=1) id, delayMs 1 1
6 T62D 延时关断 (IN=0 等待 delayMs ms 后 OUT=0) id, delayMs 1 1
7 RISING 上升沿检测 (0→1 产生一周期脉冲) id 1 1
8 SR SR 触发器 (S优先: S=1置位, R=1& S=0复位) id, S, R 2 (S=0, R=1) 1
9 RS RS 触发器 (R优先: R=1复位, S=1& R=0置位) id, S, R 2 (S=0, R=1) 1
10 FALLING 下降沿检测 (1→0 产生一周期脉冲) id 1 1

Comb 的 C 引擎自动检测逻辑

parse_xml_comb(comb_el, graph):
  1. 遍历 comb_el 的子元素 (<Inputs>, <Gate>, <Comb>, <Outputs>)
  2. 遇到子 <Comb> → 递归调用 parse_xml_comb()  ← 这就是嵌套自动检测
  3. 子 Comb 的 Gate 输出 → 父 Comb 的 Gate 输入 (自动连线)
  4. 遇到 <Inputs> → 创建 HW_INPUT 节点 → 连线到同层 Gate
  5. 遇到 <Gate> → 创建门节点 + 解析 R/S 属性
     - R="Comb#N" → 查找子 Comb 中对应 Gate 的输出
     - S="Comb#N" → 同上
     - R="Input#N" / S="Input#N" → 创建对应 Input 节点
  6. 遇到 <Outputs> → 创建 HW_OUTPUT 节点 → 连线从同层 Gate

链级别 Comb 处理 (第二遍布线):
  1. Comb 的 Gate 输出 → 链级 Gate 输入
  2. 链级 Input → 链级 Gate
  3. 链级 Gate → 链级 Output

核心结论: Comb 是 XML 中天然存在的嵌套结构C 引擎自动递归解析。前端应该:

  • 加载 XML 时自动识别 Comb 嵌套关系
  • 渲染为视觉分组容器 (矩形框)
  • 允许用户通过拖拽节点入框来创建 Comb
  • 不允许手动添加空 Comb

三、原工程 PLC Config 前端功能详细清单

3.1 导航与入口

  • Hash 路由: #plc_config
  • 导航标签: "PLC 配置" / "PLC Config"
  • 导航图标: 原工程用 emoji 🧩, 当前用 SVG cpu

3.2 多 Chain 管理

功能 描述 实现方式
Chain 标签切换 顶部标签栏,每个 Chain 一个标签 点击切换当前编辑的 Chain
Chain 标签内容 显示 "Chain N (节点数)" 实时更新
添加 Chain +Chain 按钮 创建空 Chain, 自动切换
删除 Chain -Chain 按钮 删除当前 Chain (≥2个时可用)

3.3 节点类型工具栏

每种节点类型一个按钮,点击后在 Canvas 随机位置添加:

[+INPUT] [+OUTPUT] [+OR] [+AND] [+NOT] [+T62P] [+T62D] [+RISING] [+SR] [+RS] [+FALLING]

3.4 Canvas 画布编辑器

功能 描述 交互
节点渲染 圆角矩形 + 类型名 + ID号 + 颜色区分 11种颜色方案
引脚圆点 输入引脚(左, 彩色), 输出引脚(右, 绿色) 5px 半径
连线渲染 节点间实线, 从输出引脚→输入引脚 深灰 #2c3e50
拖拽节点 按住节点拖动 20px 网格吸附
连线操作 从输出引脚拖出虚线→目标输入引脚释放 红色虚线
选中节点 单击节点高亮 白色填充 + 红色边框
删除节点 选中 + 删除按钮 同时删除关联连线 + 重编号 Gate ID
平移画布 拖拽空白区域 平移
缩放 滚轮缩放 0.5x-2.0x 缩放栏显示百分比
缩放栏 [放大] [缩小] [适应] 100% 适应 = zoom=1, pan=0
双击编辑 双击节点弹出属性 Modal 编辑 saddr/desc/delayMs/spin/rpin

3.5 Comb 组合块

功能 描述
自动识别 加载 XML 时自动解析 Comb 嵌套结构
视觉渲染 虚线圆角矩形,标签 "Comb #N"
嵌套 Comb 视觉上子 Comb 在父 Comb 内部
节点归属 Comb 内节点在视觉上位于 Comb 矩形内
创建 Comb 选中多个节点 → "成组为 Comb" 创建
解散 Comb 选中 Comb → "解散 Comb" → 节点回到链级别

3.6 XML 查看与持久化

功能 描述
XML 实时预览 只读 <pre> 标签, 随编辑实时更新
加载 XML 从 RTU 读取 cat config/PLC/Reclose_logic.xml
保存 XML 通过 WS set_file 写回 RTU
checksum 根节点自动计算 XOR checksum

3.7 操作按钮栏

[加载 XML] [保存 XML] [清空] [删除选中节点]

四、原工程 UI 设计参考

4.1 设计风格

参数 原设计值 当前值
风格 暗色工业主题 (Dark Industrial Dashboard) 暗色工业主题
主色调 Cyan/Teal (#00E5FF / #1DE9B6) Teal (#00d4aa)
背景 #0F1923 (deep navy) #0a0f16 (更深)
卡片背景 #1A2332 #111922
字体 Inter + JetBrains Mono
图标 Emoji (原工程) → SVG Lucide (重构目标) SVG 内联 Lucide
Canvas 背景 浅色网格 (#f0f2f5)

4.2 导航图标规格

页面 原 Emoji Lucide SVG 图标名 说明
仪表盘 📊 dashboard 四象限网格
开出信号 📡 signal 信号波形
开入信号 🔗 link 链接
遥控信号 zap 闪电
参数设置 🎚️ sliders 滑块
定值管理 ⚙️ settings 齿轮
数据中心 📋 database 数据库
PLC 调试 🔌 bug Bug/调试
PLC 配置 🧩 cpu CPU/芯片
实时监控 📈 activity 心电图
命令终端 💻 terminal 终端

五、重构目标与要求

5.1 必须保留/增强的功能

  • 多 Chain 标签切换
  • 11 种节点类型完整支持
  • Canvas 拖拽、连线、缩放、平移
  • 节点属性双击编辑 (含 SR/RS R/S 引脚, T62P/D delayMs)
  • XML 实时预览
  • 从 RTU 加载/保存

5.2 必须修复的问题

  • Comb 改为自动识别 — 加载 XML 时检测,不允许手动添加空 Comb
  • Comb 创建方式 — 选中多个节点 → "成组为 Comb"
  • 导航图标风格 — 恢复工业风格,尺寸与文字匹配
  • set_file 后端实现 — 确保保存功能真正可用

5.3 必须优于原工程的新功能

  • Comb 视觉边界框正确嵌套
  • SR/RS 引脚 S/R 标签显示
  • 节点颜色方案保持一致性
  • 更好的错误处理 (XML 解析失败提示)
  • 键盘快捷键 (Delete 删除, Ctrl+S 保存)

六、Comb 自动检测算法 (前端)

// 加载 XML 时的 Comb 自动检测伪代码
function detectCombsFromXml(xmlDoc):
  for each <Chain> in <PLCConfig>:
    chain.nodes = []   // 扁平存储所有节点
    chain.combs = []   // 存储 Comb 容器定义
    chain.links = []   // 存储连线

    // 1. 解析顶层元素
    parseChainElements(chainEl, chain, parentId=-1)

function parseChainElements(parentEl, chain, parentId):
  for each child in parentEl.children:
    if child.tag == 'Inputs' or 'Outputs':
      parseSignals(child, chain)
    if child.tag == 'Gate':
      parseGate(child, chain)
    if child.tag == 'Comb':
      combId = child.getAttribute('id')
      // 创建 Comb 容器 (位置由内部节点包围盒计算)
      comb = { id: combId, parentId: parentId }
      chain.combs.push(comb)
      // 递归解析 Comb 内部元素
      parseChainElements(child, chain, combId)

  // 2. Comb 位置自动计算 (后处理)
  for each comb in chain.combs:
    var nodesInComb = chain.nodes.filter(n => 位于 comb 区域)
    // 包围盒 = min/max of nodesInComb 的 x,y
    comb.x = minX - margin
    comb.y = minY - margin
    comb.w = maxX - minX + 2*margin
    comb.h = maxY - minY + 2*margin

Comb 归属判断

节点属于哪个 Comb 由以下规则确定:

  1. 来自 内 // → 属于该 Comb
  2. 来自 内子 的元素 → 属于子 Comb (嵌套)
  3. 来自 顶层元素 → 不属于任何 Comb (parentId=-1)

七、节点样式与颜色方案

节点 填充色 描边色 尺寸
INPUT #e8f5e9 浅绿 #27ae60 绿 110×34
OUTPUT #fce4ec 浅粉 #e74c3c 红 110×34
OR #fff3e0 浅橙 #e67e22 橙 76×46
AND #e3f2fd 浅蓝 #2980b9 蓝 76×46
NOT #f3e5f5 浅紫 #8e44ad 紫 76×46
T62P #fce4ec 浅粉 #c0392b 深红 86×46
T62D #fff3e0 浅橙 #d35400 深橙 86×46
RISING #e8f5e9 浅绿 #1abc9c 青绿 86×46
SR #e3f2fd 浅蓝 #3498db 亮蓝 86×52
RS #fce4ec 浅粉 #9b59b6 紫 86×52
FALLING #fff3e0 浅橙 #16a085 青 86×46

引脚颜色: 输入=同节点描边色, 输出=#27ae60 绿

Comb 视觉

  • 描边: #95a5a6 灰色虚线 (8px dash, 4px gap)
  • 填充: rgba(149,165,166,0.05) 极浅灰
  • 标签: 左上角 "Comb #N"
  • 圆角: 6px

八、文件结构

web/js/pages/plc.js        ← PLC Debug + PLC Config (重构目标)
web/css/style.css           ← PLC 相关 CSS (.chain-tabs, .plc-canvas-wrap, etc.)
web/js/i18n.js              ← PLC 相关翻译 key
config/PLC/Reclose_logic.xml ← XML 配置文件 (数据源)