# 切片 6 — 硬件集成模块(xlyPlc)*(可选)* 本切片面向会接触印刷车间的人。如果你只读写元数据,可以跳过。 xly 是印刷行业 ERP。在车间,印刷机由 PLC(programmable logic controller,工业自动化控制器)控制。每台机器暴露一串状态:运行 / 停止 / 故障、当前速度、当前张数、当前工单号等。ERP 希望实时把这些记录到正确工单上。xly 的 **`xlyPlc`** Spring Boot 模块就是做这件事的桥。 本切片覆盖桥的架构、每机型 profile 机制,以及硬件专用代码与通用框架之间的边界。 ## 记录对象 | | | |---|---| | **模块** | `xlyPlc`(代码库中的兄弟 Spring Boot 服务) | | **方向** | 单向:PLC → ERP DB(不向印刷机回发命令) | | **节奏** | 定时轮询(`PlcScheduledTasks` 中的 Spring `@Scheduled` cron,例如 `0/30 * * * * ?` 和 `0/1 * * * * ?`) | | **每机型区分** | Spring profile(`-S10`、`-T0`、`-T1`、`-15S`、`-CT`、`-yt`、`-pro`) | | **写入表** | `mftProduceReportMachineState`(dev 中约 207k 行)及相关机器状态从表 | ## 模块有多小 `xlyPlc/src/main/java/com/xly/` 只有五个文件: | 文件 | 角色 | |---|---| | `PlcApplicationBoot.java` | Spring Boot 入口 | | `web/scheduler/PlcScheduledTasks.java` | `@Component`,包含两个 `@Scheduled` cron 方法(每 30 秒和每 1 秒)驱动轮询循环 | | `web/scheduler/PlcRunStatus.java` | 当前轮询周期的内存状态 | | `web/scheduler/service/PlcToErpService.java` | 接口 | | `web/scheduler/service/impl/PlcToErpServiceImpl.java` | 实现:读 PLC、写 DB | 这就是整个桥。每个机型的协议处理通过每 profile 的 `application-*.yml` 和可选原生串口代码(`xlyRxtx`,当前在 build 中禁用,见[维护人员参考:部署](../reference/maintainer/deployment.md))引入的库完成。 ## 每机型 profile `xlyPlc/src/main/resources/` 中有 9 个 YAML 文件:默认配置加 8 个命名 profile: ```text application.yml (默认,选择 profile) application-dev.yml (开发配置) application-S10.yml (S10 机型) application-T0.yml (T0 机型) application-T1.yml (T1 机型) application-15S.yml (15S 机型) application-CT.yml (CT 机型) application-yt.yml (某客户命名 profile) application-pro.yml (生产) ``` 某个 xlyPlc 实例启动时只激活一个 profile,例如 `-Dspring.profiles.active=S10`。profile 携带该机型的串口设置、轮询频率、字节协议参数和目标 ERP DB 连接。通常是每台印刷机一个 xlyPlc 部署,或每个机型 / 机器一个部署。这是运维问题,不是客户可见功能。 ## 写入什么 轮询循环读取 PLC 寄存器,把它们转成 ERP 领域行,并写入: - `mftProduceReportMachineState`:机器状态时间序列(运行 / 停止 / 故障),此 dev DB 中 207,112 行。 - 适用时写入相关 `mftProductionReport*` 从表。 行落库后,ERP 其余部分像处理普通数据一样处理: - `viw_*` 视图把它们聚合进车间看板。 - 标准切片 1 风格模块渲染这些视图。 - 元数据层(切片 4 定制)允许客户给看板加字段,而不碰桥接代码。 ## 框架 / 硬件边界 这是 xly 对复杂问题给出的最干净故事: - **线以上(xlyEntry、xlyApi、所有元数据机制):通用框架。** 不知道印刷机、PLC 或字节协议。 - **线以下(xlyPlc):硬件专用。** 知道如何与机器通信。 二者只通过数据库通信。桥写行,框架读行。没有 RPC、没有共享进程内状态、没有回调。这使 xlyPlc: - 可独立部署;多个客户把它运行在靠近印刷机的机器上,与中心 ERP 服务器分离。 - 可独立失败:桥崩溃时,框架继续在旧机器状态上运行;框架宕机时,桥继续写入,框架恢复后看到缓冲行。 - 难以在没有真实印刷机的情况下端到端测试。多数 CI 测试只能模拟 PLC 读取。 ## 本切片引入的概念 本切片刻意作为*边界案例*,不引入新的框架概念。它用于说明:数据驱动运行时只处理框架问题;一旦行写入数据库,框架不关心它来自 PM 在**后台**手输、客户在**前台**提交,还是印刷机 PLC 通过 xlyPlc 推送。 ## 本切片使用的参考 - [维护人员:多服务部署](../reference/maintainer/deployment.md):`xlyPlc` 是可运行服务之一。部署章节需要补充车间部署说明(每机型一个桥或每机器一个桥)。 ## 待验证项 > **Item 1 — 暂缓(超出仓库可验证范围)。** 字节协议本身来自各印刷机型厂商文档,不在 xly 源码树中。每个 `xlyPlc/src/main/resources/application-.yml` 只携带**参数**(波特率、帧格式、寄存器地址、轮询调优项);**协议语义**属于印刷机厂商知识。完整记录这些内容是部署运维工作,不是针对 src / DB / web 的 wiki 审计能完成的。 1. **线缆协议。** 每个机型有不同字节协议;每个 `application-.yml` 携带参数。按机型记录协议是独立小众章节。 2. ~~**桥 → ERP DB 延迟 / 轮询间隔。**~~ **已关闭。** `PlcScheduledTasks.java` 中有两个 Spring `@Scheduled` cron 方法(未观察到 cron 字符串按 profile 变化):`0/30 * * * * ?`(每 30 秒,74 行)和 `0/1 * * * * ?`(每 1 秒,105 行)。125 行还有一个已注释的第三个 cron(`0 */2 * * * ?`),当前休眠。每 profile 参数调优发生在轮询代码读取 `application-.yml` 时,不在 cron 表达式本身。车间看板刷新独立于桥:它的 `viw_*` 聚合会在每次 FROUNT 请求时重读 `mftProduceReportMachineState`,所以印刷机发出状态后,看板最多约 30 秒能看到新行。 3. ~~**为什么 `xlyRxtx` 在 `settings.gradle` 中禁用。**~~ **已关闭。** `xly-src/settings.gradle` 的 git history 显示,`xlyRxtx` 最早在 commit `daf581311`(“1、添加串口功能 …”)中加入,用于串口能力。cleanup 分支把它注释掉,是源码裁剪的一部分:排除当前 dev DB 尚未覆盖的硬件模块。需要直接串口访问印刷机的部署可以重新启用 `settings.gradle` 中的 include。xlyPlc 本身不依赖 RXTX 也能运行;这里记录的机型依赖 TCP / Ethernet,只有串口型机型需要重新启用 RXTX。