3. 状态机设计与状态定义
WIP(在制品)跟踪系统的核心不是“记录位置”,而是“判断当前处于什么状态、下一步允许发生什么”。如果状态定义混乱,后续的条码扫描、位置上报、异常报警都会失去判断依据。本节围绕状态划分原则、有限状态机(FSM)建模、迁移条件与触发事件、异常状态处理四个层面展开,并给出可直接落地的状态定义表与迁移规则。
一、状态划分原则:互斥、可观测、可迁移
状态划分不是把车间里所有描述词都列一遍,而是遵循三条硬约束:
- 互斥性:任一时刻,一个WIP载体(托盘、料箱、单件)只能处于一个状态。例如“加工中”与“待检”不能同时成立,否则系统无法判断该不该触发检验任务。
- 可观测性:每个状态必须能由现场事件或数据判定。若“待加工”无法通过扫码、设备信号或人工确认识别,这个状态就不可用。
- 可迁移性:状态之间必须有明确的触发事件和迁移条件,不能出现“只能进不能出”的死状态,也不能出现无触发条件的自由跳转。
基于以上原则,典型离散制造场景可定义八个基础状态:待加工(WAIT_PROC)、加工中(IN_PROC)、待检(WAIT_INSP)、合格(PASS)、返修(REWORK)、报废(SCRAP)、暂存(HOLD)、转运(TRANSFER)。其中“暂存”与“转运”是位置性状态,用于表达WIP在非加工、非检验环节的停留与移动,避免把“在仓库”和“在路上”混为一谈。
二、有限状态机建模:状态、事件、迁移
有限状态机可形式化表示为五元组 M = (S, E, T, s0, F):S为状态集合,E为触发事件集合,T为迁移函数,s0为初始状态,F为终态集合。在本场景中,初始状态为“待加工”,终态为“合格”或“报废”。
触发事件来自三类信号源:人工扫码/按钮(如“开工”“报检”“判定合格”)、设备信号(如机床主轴启动、加工完成信号)、系统定时/规则(如超时未检自动转暂存)。迁移条件则是在事件之上附加的约束,例如“加工中→待检”要求设备完成信号为真且质检工位已分配。
下面用一张状态迁移图表达核心状态与迁移关系。图中实线箭头表示正常迁移,虚线箭头表示异常或回退迁移,箭头上的文字为“触发事件 / 迁移条件”。
三、迁移条件与触发事件的工程化定义
状态机能否落地,取决于迁移条件是否可编程判断。以下给出一份可直接映射为数据库约束或代码枚举的迁移规则表(示例参数为合理假设,非实测数据):
| 源状态 | 触发事件 | 迁移条件 | 目标状态 | 异常处理 |
|---|---|---|---|---|
| 待加工 | 开工扫码 | 工位空闲且设备自检通过 | 加工中 | 工位占用则拒绝并提示 |
| 加工中 | 设备完成信号 | 加工参数在公差内且质检工位已分配 | 待检 | 超时30min未完成转暂存 |
| 待检 | 检验判定 | 检验项全部通过 | 合格 | — |
| 待检 | 检验判定 | 不合格且可修复 | 返修 | 记录缺陷代码 |
| 待检 | 检验判定 | 不合格且不可修复 | 报废 | 触发报废审批流 |
| 返修 | 返修完成 | 返修工单关闭且重新排产 | 加工中 | 返修次数≥2则强制转待检 |
| 加工中 | 设备故障 | 故障未在15min内恢复 | 暂存 | 通知维修并锁定工位 |
| 暂存 | 恢复生产 | 故障清除且重新派工 | 待加工 | — |
| 待加工 | 调度指令 | 跨区转运任务生成 | 转运 | 到达后扫码确认 |
| 转运 | 到达扫码 | 目标工位与任务一致 | 待加工 | 不一致则转暂存并报警 |
表中“超时30min”“15min”“返修次数≥2”均为示例阈值,实际项目中应根据节拍、设备可靠性和质量成本调整。关键点在于:每个阈值都必须有明确的计时起点和判定周期,否则状态机会因“超时”定义模糊而失效。
四、异常状态处理:暂存、返修与报废的边界
异常状态最容易出问题的是“暂存”被滥用。暂存不是垃圾桶,它必须携带原因码和预计恢复时间。建议在数据模型中为暂存状态附加三个字段:hold_reason(设备故障/质量待判/物料短缺/调度等待)、hold_start_time、expected_resume_time。当暂存超过预计恢复时间仍未迁移,系统应升级报警,而不是静默等待。
返修与报废的边界同样需要规则化。返修的前提是存在可执行的返修工艺路线,且返修后必须重新经过检验,不能直接回到“合格”。报废则必须触发审批流,并记录报废原因、责任工序和数量,避免WIP在系统中“消失”却无账可查。
五、状态机实现要点
在代码层面,建议用枚举定义状态,用迁移表驱动状态变更,而不是在业务逻辑中散落大量 if-else。例如:
STATES = ["WAIT_PROC", "IN_PROC", "WAIT_INSP", "PASS", "REWORK", "SCRAP", "HOLD", "TRANSFER"]
TRANSITIONS = {
("WAIT_PROC", "START"): ("IN_PROC", "工位空闲且设备自检通过"),
("IN_PROC", "FINISH"): ("WAIT_INSP", "加工参数在公差内且质检工位已分配"),
("WAIT_INSP", "PASS"): ("PASS", "检验项全部通过"),
("WAIT_INSP", "REWORK"): ("REWORK", "不合格且可修复"),
("WAIT_INSP", "SCRAP"): ("SCRAP", "不合格且不可修复"),
("REWORK", "REDO"): ("IN_PROC", "返修工单关闭且重新排产"),
("IN_PROC", "FAULT"): ("HOLD", "故障未在15min内恢复"),
("HOLD", "RESUME"): ("WAIT_PROC", "故障清除且重新派工"),
("WAIT_PROC", "MOVE"): ("TRANSFER", "跨区转运任务生成"),
("TRANSFER", "ARRIVE"): ("WAIT_PROC", "目标工位与任务一致"),
}
每次状态变更应写入一条状态流水记录,包含:WIP唯一码、源状态、目标状态、事件类型、事件时间、操作人/设备、条件快照。这条流水既是追溯依据,也是后续分析状态停留时长、识别瓶颈工序的数据基础。
总结来说,WIP状态机设计的核心是:状态互斥可观测,迁移有事件有条件,异常有出口有升级。把这三件事在数据模型和代码中固化下来,后续的位置跟踪、看板展示和异常分析才有可靠的状态底座。