Files
bj_power/bj_power_mes/系统设计方案.md
T

22 KiB
Raw Blame History

工业自动化生产线管控系统 详细设计方案

文档信息

  • 版本:V2.4(最终生产版·固定槽位与批量补料)
  • 日期2026-05-01
  • 状态:可交付开发

目录

  1. 项目背景与目标
  2. 核心设计理念
  3. 系统总体架构
  4. 事件总线与一致性模型
  5. 工艺路线定义
  6. 数据库设计
  7. 工件生命周期与状态管理
  8. 调度器三层架构设计
  9. 任务(Task)状态机与生命周期
  10. 工单管理详细设计
  11. 工站接口设计
  12. 机器人子调度器与手持工具
  13. 超时与心跳机制
  14. 运行期状态校验
  15. 断电恢复与事件重放
  16. Redis数据结构设计
  17. 暂存台槽位管理与批量补料
  18. 与外部系统交互
  19. 关键技术选型
  20. 部署与扩展性
  21. 附录APLC信号与事件映射表

1. 项目背景与目标

1.1 项目背景

本系统面向一条多品种小批量柔性生产线,核心设备包括:

  • 4台CNC加工中心(CNC_1~4
  • 高压清洗机(双槽位,关门批处理,清洗时间2~3分钟/件)
  • 内窥镜检测滚筒线(自动检测分流)
  • 热能去毛刺机
  • 除锈清洗线(5位FIFO流水线)
  • 激光打标机(无上下料位,手持作业)
  • 地轨机器人(唯一搬运设备)
  • 10个接驳台(各9槽位)
  • 随行暂存台(8个固定槽位)
  • 抽检台(1号槽位用于异常工件暂存)

可加工的工件类型及机床绑定关系:

基本类型 子型号 绑定机床
A6VM107 B99414, B99487 CNC_3, CNC_4
A6VM160 B99464, B99488 CNC_1, CNC_2
A6VM200 B99259 CNC_1

1.2 建设目标

  • 工件全生命周期实时追踪与可视化
  • 事件驱动 + 状态机自动调度,无需预编排任务图
  • 多品种混流生产,灵活应对异常(插单、故障、返工)
  • 新增工件类型或设备仅需配置,不改核心代码
  • 工业级健壮性:防重复派单、防状态回退、超时心跳、分级断电恢复

2. 核心设计理念

2.1 工艺状态机驱动

每种工件定义静态工艺路线(状态机),工件实例仅保留当前工序指针、状态、上下文及物理位置。绝不预生成任务实体,所有前进步骤均由事件触发实时决策。

2.2 事件驱动 + Redis 单一真相源

  • Redis 是运行时唯一状态源,所有调度决策仅查询 Redis。
  • PostgreSQL 仅作持久化日志和审计存储,不参与在线决策。
  • PLC 信号是输入,不是状态源。
  • 每个状态变更均产生不可变事件,全局唯一 ID,实体版本号防乱序,所有处理器幂等。

2.3 调度三层解耦

调度引擎拆分为 任务生成 → 约束过滤 → 策略选择,各层独立可测,易于扩展。

2.4 机器人子调度器

调度引擎只下发抽象运输任务(取、放工件),机器人控制器自行完成路径规划、手持工具调用、重试。

2.5 工单与调度过滤

工单暂停仅修改工单自身状态,调度时通过约束过滤层排除,不污染工件状态。

2.6 暂存台固定槽位策略

暂存台提供 8 个固定槽位,工件在生产周期内独占一个槽位直到下料。补料策略:首次尽量装满(8件),后续当空位数超过 4 个时,一次性批量补满。

2.7 工业级健壮性

  • 实体版本号防并发和状态回退
  • 原子抢占防重复派单
  • Task 状态机跟踪生命周期,支持超时与重试
  • 设备心跳监控在线状态
  • 分级断电恢复策略

3. 系统总体架构

本系统为 单体应用,采用分层模块化设计,打包为单个可执行文件,内部按职责划分包(package),通过接口通信。

┌──────────────────────────────────────────────────────┐
│                   人工终端 (React)                   │
└──────────────────────┬───────────────────────────────┘
                       │ WebSocket / HTTP
┌──────────────────────▼───────────────────────────────┐
│               go-zero HTTP Server (API层)            │
│  ┌─────────┐  ┌──────────┐  ┌────────────────────┐  │
│  │工单管理 │  │看板/监控 │  │人工交互接口        │  │
│  └────┬────┘  └────┬─────┘  └────────┬───────────┘  │
│       │            │                │               │
│  ┌────▼────────────▼────────────────▼─────────────┐  │
│  │              业务逻辑层 (Service)              │  │
│  │  ┌────────────┐  ┌───────────┐  ┌──────────┐  │  │
│  │  │工单服务    │  │调度引擎   │  │状态管理  │  │  │
│  │  └────────────┘  └───────────┘  └──────────┘  │  │
│  └───────────────────────┬───────────────────────┘  │
│                          │                          │
│  ┌───────────────────────▼───────────────────────┐  │
│  │              基础设施层 (Infra)               │  │
│  │  ┌──────────┐  ┌──────────┐  ┌────────────┐  │  │
│  │  │事件总线  │  │PLC适配器 │  │机器人通信  │  │  │
│  │  │(Redis   │  │(OPC-UA/  │  │(TCP/寄存器)│  │  │
│  │  │ Streams) │  │ Modbus)  │  │            │  │  │
│  │  └──────────┘  └──────────┘  └────────────┘  │  │
│  └───────────────────────┬───────────────────────┘  │
│                          │                          │
│       Redis (SSOT)       PostgreSQL (持久化)        │
└──────────────────────────────────────────────────────┘

4. 事件总线与一致性模型

4.1 事件结构

type Event struct {
    ID            string    // UUIDv7
    EntityID      string    // 如 "job:J123"
    EntityVersion int       // 事件基于的实体版本
    Type          string    // 事件类型
    Source        string    // 来源模块/设备
    Timestamp     time.Time
    Payload       map[string]interface{}
}

4.2 原子更新与版本控制

  • 每个实体在 Redis Hash 中存储 version(整数)。
  • 应用事件时,使用 Lua 脚本原子校验:当前版本必须等于事件携带版本,否则拒绝(过期事件)。
  • 校验通过后更新状态并递增版本。

4.3 写入路径

  1. 生成事件对象(携带当前版本)。
  2. 发布到 Redis Stream (XADD)。
  3. 消费协程调用 StateManager.ApplyEvent 执行 Lua 脚本更新 Redis。
  4. 异步写入 PostgreSQL。

4.4 幂等与重放

  • 实体记录 last_event_id,重复事件直接跳过。
  • 断电恢复时可从 PG event_log 按顺序重放事件,安全重建 Redis 状态。

5. 工艺路线定义

5.1 工序类型

类型 说明 资源需求
LOAD 上料并首次扫码 机器人+接驳台
BUFFER_STAGE 暂存台积聚等待 暂存台特定槽位(分配后固定)
MACHINING CNC加工 CNC_1~4(可限定)
WASH 高压清洗(成对关门) 高压清洗机
INSPECTION 内窥镜检测 检测滚筒线
JUDGE 检测结果判定
RUST_WASH 除锈清洗 除锈清洗线(FIFO)
FINAL_SCAN 最终扫码(手持) 扫码器
LASER_MARK 激光打标(手持) 激光打标机
DECISION 抽检/下料分支 机器人

5.2 首次扫码特殊规则

机器人从接驳台抓取工件后直接手持扫码:

  • 成功 → 分配暂存台空闲槽位,放入,工件进入 BUFFER_STAGE(状态 ON_BUFFER)。
  • 失败 → 工件放回原接驳台槽位,状态 SUSPENDED,原因 SCAN_FAILED,人工介入。

5.3 示例工艺路线(A6VM107

{
  "recipe_id": "R-A6VM107",
  "steps": [
    {"step_id":"10","type":"LOAD","tool":"SCANNER","next":"20","branches":{"FAIL":"_RETURN_BAY"}},
    {"step_id":"20","type":"BUFFER_STAGE","next":"30"},
    {"step_id":"30","type":"MACHINING","allowed":["CNC_3","CNC_4"],"next":"40","step_timeout":600},
    {"step_id":"40","type":"UNLOAD","next":"50"},
    {"step_id":"50","type":"WASH","next":"60","step_timeout":300},
    {"step_id":"60","type":"UNLOAD","next":"70"},
    {"step_id":"70","type":"INSPECTION","next":"80"},
    {"step_id":"80","type":"JUDGE","branches":{"PASS":"90","FAIL":"900"}},
    {"step_id":"90","type":"UNLOAD","next":"100"},
    {"step_id":"100","type":"DEBURR","next":"110","step_timeout":300},
    {"step_id":"110","type":"UNLOAD","next":"120"},
    {"step_id":"120","type":"RUST_WASH","next":"130"},
    {"step_id":"130","type":"UNLOAD","next":"140"},
    {"step_id":"140","type":"FINAL_SCAN","tool":"SCANNER","next":"150","branches":{"FAIL":"145"}},
    {"step_id":"145","type":"LASER_MARK","tool":"LASER","next":"150"},
    {"step_id":"150","type":"DECISION","branches":{"SAMPLE":"200","NORMAL":"210"}},
    {"step_id":"200","type":"PLACE_SAMPLING"},
    {"step_id":"210","type":"PLACE_AGV"}
  ]
}

_RETURN_BAY 表示放回原接驳台槽位并挂起。


6. 数据库设计

6.1 基础主数据表

product_type

字段 类型 说明
id varchar(20) PK A6VM107, A6VM160, A6VM200
name varchar(50)
recipe_id varchar(20) FK
is_active boolean

recipe

字段 类型 说明
id varchar(20) PK
name varchar(50)
version int
create_time timestamptz

recipe_step

字段 类型 说明
step_id varchar(10) PK
recipe_id varchar(20) FK
step_name varchar(50)
step_type varchar(20) 工序类型
resource_type varchar(50) 所需工站类型
tool_type varchar(20) 手持工具类型
allowed_resources jsonb 允许的设备列表
processing_params jsonb 工时等
next_step_default varchar(10)
next_step_branches jsonb 分支映射
step_timeout int 超时秒数
description text

equipment

字段 类型 说明
id varchar(20) PK
type_code varchar(20)
name varchar(50)
status varchar(20) 从Redis推导,此字段仅作离线参考
slot_count int
ip_address varchar(45)
location varchar(50)

6.2 业务数据表

work_order

字段 类型 说明
id varchar(30) PK
product_type_id varchar(20) FK
quantity int
source_bay_slot_id varchar(30) FK
status varchar(20) CREATED/IN_PROGRESS/PAUSED/COMPLETED/CANCELLED
context jsonb
created_time timestamptz
updated_time timestamptz
completed_time timestamptz

job

字段 类型 说明
id varchar(30) PK
work_order_id varchar(30) FK
product_type_id varchar(20) FK
recipe_id varchar(20) FK
current_step_id varchar(10) FK
status varchar(20) 见7.1
position_type varchar(20) ON_EQUIPMENT/ON_BUFFER/IN_HAND
position_ref_id varchar(50) 位置引用(含暂存台槽位ID
context jsonb 子型号、扫码数据等
priority int
suspended_reason text
version int 事件版本控制
last_event_id varchar(36)
created_time timestamptz
last_updated timestamptz

job_step_instance

字段 类型 说明
id bigserial PK
job_id varchar(30) FK
step_id varchar(10) FK
attempt_no int
status varchar(20) IN_PROGRESS/COMPLETED/FAILED
equipment_id varchar(20)
start_time timestamptz
end_time timestamptz
result jsonb

task

字段 类型 说明
id varchar(36) PK UUID
job_id varchar(30) FK
type varchar(30) TRANSPORT/HANDHELD_SCAN…
status varchar(20) CREATED/DISPATCHED/RUNNING/SUCCESS/FAILED/TIMEOUT
from_pos jsonb
to_pos jsonb
assigned_robot varchar(20)
started_time timestamptz
completed_time timestamptz
result jsonb

task_log / event_log 略。


7. 工件生命周期与状态管理

7.1 Job 状态

状态 含义 转换示例
CREATED 已创建,在接驳台 → IN_HANDLING
IN_HANDLING 机器人操作中 → ON_BUFFER(扫码成功) / SUSPENDED(扫码失败)
PROCESSING 设备加工中 → WAITING_UNLOAD
WAITING_UNLOAD 加工完成待取走 → IN_HANDLING
ON_BUFFER 固定在暂存台槽位上 → IN_HANDLING
WAITING_DECISION 等待判定(检测后) → COMPLETED / SCRAPPED / ON_BUFFER
COMPLETED 正常下线,释放暂存台槽位 终态
SCRAPPED 报废,释放暂存台槽位 终态
SUSPENDED 异常暂停(扫码失败等) → 恢复

7.2 暂存台槽位生命周期

  • 扫码成功后分配一个空闲槽位(编号1~8),写入 position_ref_id
  • 工件全程独占该槽位,直到进入 COMPLETED 或 SCRAPPED 状态后释放。

8. 调度器三层架构设计

8.0 调度触发机制(事件驱动)

  1. 状态管理器在原子更新 Redis 后,将新变为 ON_BUFFERWAITING_UNLOAD 的工件 ID 推入 Redis Sorted Set sched:ready_jobs
  2. 调度引擎阻塞在 ZPOPMAX 上,仅处理变动工件,无全局扫描。
  3. 处理完若无可行任务,工件放回 sched:ready_jobs 等待下一次事件。

8.1 任务生成层

根据 job.current_steprecipe_step 生成候选动作列表。

8.2 约束过滤层

过滤设备不可用、工单暂停、工件暂停、工具锁冲突、批处理未满、超时挂起等。

8.3 策略选择层

优先级排序:

  1. 紧急转移(WAITING_UNLOAD
  2. 成组装卸(高压清洗机)
  3. 设备上料
  4. 暂存台批量补料(空位 > 4 触发)
  5. 手持作业
  6. 普通搬运

8.4 原子抢占

Lua 脚本原子地将工件状态从 ON_BUFFER 改为 IN_HANDLING,成功则创建 Task。


9. 任务(Task)状态机与生命周期

CREATED → DISPATCHED → RUNNING → SUCCESS
                    ↓           ↓
                  FAILED      TIMEOUT
  • CREATED:调度生成
  • DISPATCHED:已下发机器人
  • RUNNING:机器人开始执行
  • SUCCESS/FAILED/TIMEOUT:终态
  • FAILED 可重试,TIMEOUT 则工件回退。

10. 工单管理详细设计

  • 创建:选择接驳台槽位、工件类型(可指定子型号),生成工单和 N 个 Job。
  • 暂停/恢复:工单状态改为 PAUSED,过滤层排除;恢复改回 IN_PROGRESS。
  • 单工件暂存:直接设置 Job 状态为 SUSPENDED。
  • 返工:修改 current_step,新增 job_step_instance

11. 工站接口设计

type Station interface {
    ID() string
    Type() string
    GetStatus() StationStatus // IDLE, BUSY, WAITING, FAULT
    CanAccept(jobType string) bool
    Execute(cmd StationCommand) (AssignedSlot string, error)
    OnEvent(event StationEvent)
}

设备占用通过 Redis 推导,不冗余存储。


12. 机器人子调度器与手持工具

调度引擎下发抽象任务,机器人控制器自行完成运动控制、工具调用(通过 HandheldTool 接口),工具用 Redis 锁互斥。


13. 超时与心跳机制

  • 工序超时step_timeout 超时自动挂起。
  • 任务超时Task 创建后超时回退。
  • 设备心跳equipment:{id}:heartbeat TTL 5s,丢失则过滤。

14. 运行期状态校验

周期性抽查 PLC 实际工件 vs Redis 逻辑,不一致则挂起报警。


15. 断电恢复与事件重放

15.1 恢复分级

级别 条件 措施
L1 自动 CREATED/ON_BUFFER/WAITING_RESOURCE 直接恢复
L2 半自动 PROCESSING 且 PLC 确认完成 转 WAITING_UNLOAD 自动恢复
L3 人工 IN_HANDLING/关门中/位置不明 人工确认处置

15.2 重放

从 PG 事件流按顺序重放,版本号与幂等保证正确性。


16. Redis 数据结构设计

  • job:{id} Hash:状态、位置、版本、last_event_id
  • equipment:{id} Hash:设备状态
  • equipment:{id}:heartbeat String TTL
  • task:{id} Hash:任务状态
  • sched:ready_jobs Sorted Set:按优先级排队的就绪工件
  • buffer:slots:bitmap String8位 Bitmap 表示暂存台槽位占用
  • tool:lock:{type} String TTL:手持工具锁

17. 暂存台槽位管理与批量补料

17.1 槽位分配与释放

  • 暂存台共 8 个槽位,编号 1~8,通过 Redis Bitmap 管理。
  • 分配:首次扫码成功后,寻找第一个空闲槽位(位值为0),置1,记录槽位号到 job 的 position_ref_id
  • 占用期:工件在生产全程独占该槽位,即使被取走去加工,槽位依然保持占用。
  • 释放:工件状态变为 COMPLETED 或 SCRAPPED 时,对应 Bitmap 位置 0。

17.2 批量补料规则

  • 冷启动:系统启动时若暂存台空位 = 8,触发连续上料,尽可能装满 8 件。
  • 运行中触发:每次槽位释放(工件下线)后,检查 Bitmap 中 0 的个数。若 空位数 > 4,立即触发批量补料。
  • 补料数量:N = min(空位数, 接驳台上待上料工件数),目标是将暂存台补满至 8。
  • 实现:状态管理器在处理工件终态事件后调用 BufferManager.CheckAndRefill(),若满足条件则向调度引擎提交高优先级批量上料命令(优先级 4),生成一串“抓取→扫码→入暂存台”任务,连续执行直至补满或无料可上。

18. 与外部系统交互

  • AGV:托盘到位/成品送出通过事件通知。
  • MES(可选):接收工单,上报履历。
  • 人工终端:工单、抽检、暂停/恢复、断电恢复看板。

19. 关键技术选型

组件 技术
后端语言 Go 1.23.4
框架 go-zero v1.3.8(单体)
ORM ent v0.14.5
数据库 PostgreSQL
缓存/状态/事件 Redis (SSOT, Streams, Lua)
PLC 通信 OPC-UA / Modbus TCP
前端 React 19 + Semi Design + Zustand + Vite 7

20. 部署与扩展性

  • 单体二进制部署,依赖 Redis + PostgreSQL。
  • 模块接口解耦,未来可拆分微服务。
  • 新增工件/设备仅需数据库配置。

附录APLC信号与事件映射表

A.1 状态信号(PLC → 系统)

PLC信号 地址 类型 系统事件
CNCDone1~4 M1140.0~3 bool MACHINE_TASK_COMPLETE
WasherDone M1144.0 bool MACHINE_TASK_COMPLETE
DeburrDone M1145.0 bool MACHINE_TASK_COMPLETE
CleaningDone M1146.0 bool MACHINE_TASK_COMPLETE
MeasureOK/NG M1148.0/1 bool INSPECTION_PASS/FAIL
SamplingOK/NG M1151.0/1 bool SAMPLING_PASS/FAIL

A.2 指令信号(系统 → PLC

指令 地址 参数 任务类型
FetchWorkpieceFromDock M1000 类型,接驳台号,槽号 PICK
PlaceWorkpieceToDock M1010 类型,接驳台号,槽号 PLACE
FetchWorkpieceFromTempStation M1020 类型,暂存位 PICK
PlaceWorkpieceToTempStation M1030 类型,暂存位 PLACE
PlaceWorkpieceToMachine M1040 类型,设备ID,槽位 LOAD
FetchWorkpieceFromMachine M1050 类型,设备ID,槽位 UNLOAD
ExchangeWorkpieceToMachine M1060 类型,设备ID,槽位 EXCHANGE
PlaceWorkpieceToRollingLine M1070 类型 LOAD
FetchWorkpieceFromRollingLine M1080 类型 UNLOAD
PlaceWorkpieceToSamplingStation M1090 类型 PLACE
FetchWorkpieceFromSamplingStation M1100 类型 PICK
MoveWorkpieceToMarkingStation M1110 类型 HANDHELD_MARK
StartScanCode M1130 类型,轮次 HANDHELD_SCAN

本方案覆盖了从事件驱动、状态机、调度引擎到现场PLC信号的全部细节,可直接指导开发团队进行实现。