fix: rebuild MES as compilable go-zero+ent backend (renamed bj_power_mes), restore 3 workstation projects from pristine original, align naming; all Go projects go build clean

This commit is contained in:
SunYF
2026-08-27 10:56:41 +08:00
parent 380715f8a9
commit 371b494c54
523 changed files with 67923 additions and 24758 deletions
+93 -80
View File
@@ -4,38 +4,46 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## 项目概述
磨床自动化单元管控系统。控制西门子 PLC 驱动的工业机器人串联 6 台设备完成毛坯到成品的全流程加工
液压马达后盖(A6VM107/160/200CNC 产线管控系统。控制西门子 PLC 驱动的工业机器人 + 4台CNC + 清洗机 + 去毛刺机 + 检测设备 + 接驳台
- **后端**: Go 1.25go-zero v1.8.3ent ORM v0.14.5PostgreSQL
- **后端**: Go 1.25go-zero v1.8.3ent ORM v0.14.5PostgreSQLRedis(缓存辅助)
- **前端**: React 19 + Semi Design UI v2.94 + Zustand + Vite 7`frontend/`pnpm
- **PLC**: 西门子 S7 协议Snap7
- **PLC**: 西门子 S7 协议 + FANUC FOCAS + OKUMA OspDirect
- **数据采集**: `back_cover_dc/`(独立项目,Modbus/S7/Focas/OSP-MC/OSP-LATHE 多协议采集)
- **大屏看板**: `dashboard-server/` + `dashboard-client/`(4K 深色大屏,产线概览 + 设备监控 + OEE)
## 关联项目
本仓库位于 `F:\Workspace\Hardman\hougai\`,同级目录还有:
| 项目 | 说明 |
|------|------|
| `back_cover_dc/` | 多协议数据采集服务(Modbus/S7/Focas/OSP),独立 Go 项目,GORM + Fiber |
| `dashboard-server/` | 大屏看板后端,Go + Fiber + sqlx,直连 back_cover 数据库只读查询 |
| `dashboard-client/` | 大屏看板前端,React + TypeScript + ECharts + Semi Design4K 深色主题 |
| `okuma_dc/` | OKUMA 采集器(已废弃,功能已合并到 back_cover_dc 的 osp 协议) |
## 常用命令
```bash
# 后端
go run . -f etc/spherical-api.yaml # 开发运行
go run cmd/mockrun/main.go -debug -jobs 3 # Mock 全流程模拟
go run cmd/debug/main.go -f etc/spherical-api.yaml -p 8890 # 调试面板
go run hougai.go -c etc/hougai-api.yaml # 开发运行
go run cmd/mockrun/main.go # Mock 模拟完整订单流程
go run cmd/debug/main.go -f etc/hougai-api.yaml # 调试面板(端口 8890
build.bat # 构建 bin/hougai.exe
# 前端
cd frontend && pnpm dev # Vite 开发服务器
cd frontend && pnpm build # 构建,输出到 public/
# 构建
./build.sh # macOS/Linux 构建脚本
cd frontend && pnpm dev # Vite 开发服务器5173 → 8888
cd frontend && pnpm build # 嵌入 Go 二进制
# 代码生成(修改 schema/api 后必须执行)
cd schema && go generate # ent ORM
cd apis && go generate # handler/logic/types
# 数据库初始化
go run schema/tools/migrate.go # 建表
go run schema/tools/data.go seed signals # 导入种子数据 + 信号
cd schema && go generate # ent ORM
cd apis && go generate # handler/logic/types
# 测试
go test ./internal/processor/... # 单包测试
go vet ./... # 静态分析
go test ./internal/processor/... # 单包测试
go test -cover ./... # 覆盖率(Windows 上 -race 不可用)
go vet ./... # 静态分析
```
## 全局规则
@@ -46,16 +54,17 @@ go vet ./... # 静态分析
- 不用 `goctl`/`ent init`,用 `cd apis && go generate` / `cd schema && go generate`
- API 变更先改 `apis/*.api`schema 变更先改 `schema/*.go`,再生成
- **processor 包用 `log/slog`**,不用 `go-zero/core/logx`
- 所有命令加 `rtk` 前缀
## 编码准则
**先想后写**:不确定时停下来提问。有多种解读时列出选项,不要默默选择。有更简单方案时提出反对意见。
**简单优先**:用最少代码解决问题。不为单次使用创建抽象。不写不可能出现的错误处理。
**简单优先**:用最少代码解决问题。不为单次使用创建抽象。不写不可能出现的错误处理。200 行能变 50 行就重写。
**精准改动**:只改必须改的部分。不改相邻代码、注释、格式。不改没坏的东西。风格匹配现有代码。
**精准改动**:只改必须改的部分。不改相邻代码、注释、格式。不改没坏的东西。风格匹配现有代码,即使你本会写成另一种风格。只清理你自己的改动产生的孤儿引用/import/变量
**防御式编程**所有函数返回 error 不许直接 `_` 忽略,必须日志告警或向上抛出。禁止隐性失败
**目标驱动**把任务转化为可验证目标。"修 bug" → "先写能复现的测试,再修"。多步骤任务先列简明计划。让成功标准明确,才能独立推进
## 架构
@@ -63,100 +72,104 @@ go vet ./... # 静态分析
PostgreSQL 是唯一运行时真相源。所有状态写入由 `ProductionEventLoop` 单线程串行处理。HTTP handler 直接查询 ent/PostgreSQL(读取无需经过 event loop)。
**状态写入路径**HTTP handler → EventLoopMessage → ProductionEventLoop → DBState 条件更新 → ent → PostgreSQLPLC 信号 → SignalRouter → EventLoop 投递 → handleMachineSignal → Actor 标记槽位 → trySchedule
**状态写入路径**HTTP handler → EventLoopMessage → ProductionEventLoop → DBState 条件更新 → ent → PostgreSQLPLC 信号 → SignalRouter → Actor.signalCh → Actor 写 DB + 投递 MACHINE_DONE → EventLoop 推进步骤 + 调度
### eventloop 包(`internal/processor/eventloop/`
- **`ProductionEventLoop`**`loop.go`)— 从 `msgCh`256)接收消息串行处理,`time.Timer`60s)触发 `trySchedule`。消息类型:CommandSTART_ORDER/PAUSE_ORDER/...)、ExternalEventMACHINE_DONE/MACHINE_SIGNAL/SCHEDULE_TICK)、WorkerResult
- **`DBState`**`dbstate.go`)— ent 条件更新:`AdvanceStep`(链式跳步)、`CompleteStep``FinishJob``SetEquipmentSlot`
- **`RecoverOnStartup`**`recovery.go`)— 启动恢复未完成工单
- **`RuntimeSnapshot`** — DB 只读快照,缓存工件当前步骤信息
- **`ProductionEventLoop`**`loop.go`)— 从 `msgCh`256)接收消息串行处理,`time.Timer`60s)触发 `trySchedule`。消息类型:CommandSTART_ORDER/PAUSE_ORDER/...)、ExternalEventMACHINE_DONE/INSPECTION_RESULT/STEP_TIMEOUT)、WorkerResult
- **`DBState`**`dbstate.go`)— ent 条件更新:`AdvanceStep`(链式跳步,上限 100 次防循环)、`CompleteStep``FinishJob``SetEquipmentSlot`Actor 独占调用)
- **`RecoverOnStartup`**`recovery.go`)— IN_PROGRESS→PAUSED + 校验 slot 一致性,不一致项创建 manual_action
- **`RuntimeSnapshot`** — DB 只读快照,替代旧 JobRuntime 状态机
### processor 包
- **`scheduler_bridge.go`** — RuntimeSnapshot→JobView→CandidateTask→RobotAction 映射。补料在调度管线**之前**处理。`prePairWasherLoads` 按 TargetID:Category 分组配对。`findExchangePair` 校验同 category
- **`Replenisher`** — 接驳台→暂存台补料。硬编码配额(8 槽位按活跃 category 分配:3类→3:3:22类→4:4/5:3,单类→8)。触发:占用 ≤ quota/2
- **`RobotWorker`** — 适配 `robot.Controller``action.HardwareWorker` 接口。通过 Actor 同步方法操作槽位,不直接写 DB。设备特定 PLC 操作(Load/Unload/Exchange)委托 Station 接口,不再包含 machineID 硬编码
- **`JobProcessor`** — 订单生命周期 + jobs map 跟踪
### 调度器(三层架构)
Generator(步骤→候选动作)→ Filter(链式约束:MachineBusy/MachineEmpty/CacheSlotFull/OrderPaused/JobSuspended/ExchangePair/MachineWait)→ Policy(优先级规则)。`trySchedule` 触发。
一次调度只派遣一个 Worker 动作,确保机器人串行执行。
Generator(步骤→候选任务)→ Filter(链式约束:MachineBusy/TempSlotFull/OrderPaused/...)→ Policy8 条优先级规则)。`trySchedule` 触发。
### Actor 系统
每台设备一个 MachineActormutex 保护的状态结构体),负责槽位状态管理。不写 DB,不操作 PLC
每台设备一个 Actorgoroutine + channel),独占槽位状态和 equipment_slot DB 写入权
**槽位状态机**`Empty → Occupied → Done → Empty`
**槽位状态机**`Empty → Occupied → Done → Empty`外部组件无权直接写 equipment_slot。
**信号流**PLC → SignalRouter 轮询(上升沿检测)→ EventLoop.handleMachineSignal → Actor.MarkSlotDone → 投递 MACHINE_DONE → trySchedule。
**信号流**PLC → SignalRouter 轮询(上升沿per-actor 通道容量 4)→ Actor.handleSignal → 标记 DONE + 写 DB → 投递 MACHINE_DONE → EventLoop
### 设备类型
**通信模式**RobotWorker→Actor(同步),EventLoop→Actor(异步消息),Actor→EventLoop(异步事件)
| 设备 | 槽位数 | 支持 Exchange |
|------|--------|--------------|
| GRINDER 磨床 | 1 | 是 |
| TURN_TABLE 转台 | 1 | 是 |
| AIR_BLOW 气吹 | 1 | 否 |
| FULL_CHECK 全检台 | 2 | 否 |
| CACHE 缓存台 | 1 | 否 |
| DOCK 接驳台 | 84 | 否 |
**TempStoreActor**:暂存台槽位唯一写入口。`AllocateSlot`/`ReleaseSlot`(同步,补料器调用)、异步消息循环处理 ALLOCATE/RELEASE/RESTORE。
### Recipe Decision/Judge
4 种 `decisionType`:空(无条件设 key)、`negate_bool``scan_mismatch``signal_true`(需实时读 PLC,只能 in trySchedule 处理)。非 signal_true 由 AdvanceStep 内联链式推进。
### Category 活跃工单互斥
每个 category 最多一个活跃工单(IN_PROGRESS 或 PAUSED)。创建时后端强制校验 + 前端下拉过滤已占选项。
### 事件总线与 EventLog
`LocalBus`(进程内 channel)。EventLogWriter 订阅所有事件,批量写入 `event_log`。SSE Bridge 推送到前端。
`LocalBus`(进程内 channel)。EventLogWriter 订阅所有事件,批量写入 `event_log`batch 20/1s。SSE Bridge 推送到前端。
**SSE vs HTTP API 格式差异**SSE 结构化字段在 `payload` 内,HTTP API 在顶层。前端 `normalizeEventLog()` 统一适配。
### 补料 & 废料搬运
补料:trySchedule 前检查 → BuildReplenishCandidate → 预分配暂存槽位 → RobotWorker 执行 replenish → EventLoop 处理结果。
扫码失败两条路径:补料扫码失败→保留槽位标记 WAITING_WASTE→ActionLoadWaste 搬运;标准扫码失败→工件直接放废料台→释放槽位+Scrap。ActionLoadWaste 豁免 OrderPaused/JobSuspended 约束。
### 恢复系统
启动时 `RecoverOnStartup` 恢复未完成工单,校验一致性。工单恢复由用户手动触发。
启动时 `RecoverOnStartup` 将 IN_PROGRESS → PAUSED 并校验一致性(不一致项创建 ManualAction。工单恢复由用户手动触发。
### 抽检台
machineID=9SAMPLING 类型,1槽位。OP100 Decision signal_true 读 SamplingRequest → 分支到 SAMPLING 步骤。onInspect 回调判定合格/不合格。
## 数据库
PostgreSQLent ORMschema 在 `schema/`,生成在 `ent/`,自动迁移。
PostgreSQL `127.0.0.1:5432`,库 `back_cover`,用户 `postgres`ent ORMschema 在 `schema/`,生成在 `ent/`,自动迁移。
核心表:work_order、job、equipmentequipment_slotreciperecipe_step、signal、alarm、event_log。
核心表:work_orderfinishedNum/failNum 原子累加)、jobcurrent_step_id、equipment/equipment_slotbatch 字段)、dock_slot、product_typecategory: A6VM107/160/200/recipe/recipe_stepstep_id: OP10-OP120next_step_default/branches)、signalPLC 地址映射)、alarm、manual_action、event_log/task_log。
## 前端
React 19 + Semi Design UI v2.94 + Zustand + HashRouter。SSE 实时更新。
React 19 + Semi Design UI v2.94 + Zustand + HashRouter。SSE 实时更新。路由:`/dashboard`(主控面板)、`/work-order``/workpiece``/equipment``/alarm``/recipe``/system`。WorkOrderPanel 通过 SideSheet 弹窗展示详情。
## 配置
`etc/spherical-api.yaml` — 端口 8888。`Mock.Enable=true` 时使用 MockPLC 无硬件测试
`etc/hougai-api.yaml` — 端口 8888。`Mock.Enable=true` 时使用 MockPLC/MockMarking 无硬件测试。Redis 仅用于缓存辅助
## 架构概览
```
internal/
├── action/ # 动作定义(RobotAction 结构体 + 校验方法
├── action/ # RobotAction + HardwareWorker 接口(独立包,避免循环依赖
├── alarm/ # 报警服务
├── engine/ # 全配置化流程引擎(ACQUIRE→EXECUTE→WAIT→COMPLETE
│ ├── engine.go # 核心引擎,TryAdvanceJob 主循环,AlarmService 接口
│ ├── acquirer.go # 资源获取,SELECT FOR UPDATE 事务,死循环检测+报警
│ ├── executor.go # 信号发送,按 sort_order 写入 PLC,失败报警
│ ├── completer.go # 后置操作+Done 信号匹配,资源释放/状态设置/跳转
│ ├── decision.go # 决策步骤处理,按 priority 匹配条件分支
│ ├── db_ops.go # 数据库操作封装,加载配置、读写资源
│ ├── adapter.go # I/O 层适配器,桥接引擎与 SignalRouter/PLC
── types.go # 类型定义,Job/JobStep/StepSignal/StepAction
├── eventlog/ # EventLog 持久化
├── processor/ # 核心引擎(旧架构,仍运行中
│ ├── actor/ # MachineActor + SignalRouter
│ ├── eventloop/ # ProductionEventLoop + DBState + 调度桥接 + 恢复
│ ├── scheduler/ # Generator/Filter/Policy 三层调度(将被 engine 替代)
│ ├── plcactions/ # PlcExecutorPLC 信号握手)
│ ├── steplog/ # 步骤日志
│ ├── factory.go # BuildProductionLine 产线组装
│ ├── job_processor.go / plc_worker.go
│ └── recipe_loader.go
├── svc/ # ServiceContext 根容器
├── robot/ # 机器人控制器
├── eventlog/ # EventLog 持久化(订阅 EventBus,批量写入
├── processor/ # 核心引擎
│ ├── actor/ # Actor 模型(MachineActor + TempStoreActor + SignalRouter
│ ├── station/ # Station 接口(设备特定 PLC 操作:Load/Unload/Exchange + 扩展接口)
│ ├── tool/ # 手持工具(Scanner/LaserMarker
│ ├── scheduler/ # Generator/Filter/Policy 三层调度
│ ├── eventloop/ # DB SSOT 事件循环 + 调度桥接 + 恢复
│ ├── factory.go # BuildProductionLine 产线组装(Actor + Station
── job_processor.go / robot_worker.go / replenisher.go
│ └── interface.go
├── svc/ # DI 组装(ServiceContext
├── robot/ # PLC 机器人控制(dock/machine/temp_station/washer/...
├── sse/ # SSE 实时推送
── plc/ # PLC 连接管理
└── preload/ # 信号地址/产品类型内存缓存
── preload/ # DB 数据内存缓存(PLC 信号映射 + Category 映射)
```
### engine 包(新架构)vs processor 包(旧架构)
## 已知问题
| 维度 | engine(新) | processor(旧,仍运行) |
|------|------------|----------------------|
| 定位 | 纯执行器,零业务知识 | 包含业务逻辑(if磨床/接驳台) |
| 触发 | 事件驱动(EventLoop 调用) | 消息驱动(msgCh channel |
| 调度 | 资源-based,按 job_step 推进 | 过滤器链 + 候选动作生成 |
| 并发 | SELECT FOR UPDATE 事务 | 单 goroutine 串行 + atomic.Bool |
| 配置 | 全部 DB 子表配置 | 代码硬编码 + 部分 DB |
- `internal/preload/``internal/robot/` 有构建失败的测试
- `internal/camera/` 测试需真实硬件
- Windows 上 `-race` 不可用