215 lines
9.3 KiB
Markdown
215 lines
9.3 KiB
Markdown
# 高压清洗机 FANUC 宏变量控制方案(待确定)
|
||
|
||
## 一、业务背景
|
||
|
||
高压清洗机(设备ID=5)的加工程序按零件号分成 **9 组**,通过 FANUC(发那科)CNC 宏变量 `#666`(左工位)和 `#888`(右工位)的值来调用对应的子程序(O1001~O1018)。
|
||
|
||
当前软件只发送 `workpieceType`(毛坯号,即 product_type 主键ID)给 PLC,**没有**发送零件号和 FANUC 宏变量的功能,需要新增。
|
||
|
||
## 二、业务规则
|
||
|
||
### 1. 零件号 → 组号映射(9组,共19个零件号)
|
||
|
||
| 组号 | #666(左) | #888(右) | 种类 | 毛坯号 | 零件号 |
|
||
|---|---|---|---|---|---|
|
||
| 1 | 1 | 1 | A6VM107 | B99414 | B02858、B20044、B20223、B20480 |
|
||
| 2 | 2 | 2 | A6VM107 | B99414 | B20177、B20248、B20538 |
|
||
| 3 | 3 | 3 | A6VM107 | B99487 | B20227、B20257 |
|
||
| 4 | 4 | 4 | A6VM160 | B99464 | B20141 |
|
||
| 5 | 5 | 5 | A6VM160 | B99464 | B20061、B20235 |
|
||
| 6 | 6 | 6 | A6VM160 | B99464 | B02943 |
|
||
| 7 | 7 | 7 | A6VM160 | B99464 | B20149 |
|
||
| 8 | 8 | 8 | A6VM160 | B99488 | B20240 |
|
||
| 9 | 9 | 9 | A6VM200 | B99259 | B02533、B02681、B20102、B20144 |
|
||
|
||
> 注:第9组零件号以你核对过的 `临时.txt` 为准(B02533);手写稿中记为 B20533,旧Excel图片中亦为 B02533。
|
||
|
||
### 2. 高压清洗机运行流程(新)
|
||
|
||
```
|
||
放料前:
|
||
1. 从工单取出零件号(新建工单时用户选择,存入子表)
|
||
2. 根据零件号查映射表,得到组号(1~9)
|
||
3. 通过 FANUC(gofocas 库)写入宏变量:
|
||
左工位 → #666 = 组号
|
||
右工位 → #888 = 组号
|
||
4. 通过 PLC 发送放料命令(M1040,现有逻辑不变)
|
||
5. 通过 PLC 发送启动命令(M1144.2,现有逻辑不变)
|
||
|
||
清洗完成后:
|
||
6. 两个槽位都必须完成,才能取料
|
||
7. 禁止换料(exchange),先全部取下,再单独放入
|
||
```
|
||
|
||
## 三、改动清单(按模块)
|
||
|
||
### 1. 数据库(新增2张表 + 1个字段)
|
||
|
||
**新表 `part_no`(零件号表)**:存零件号、所属毛坯号、清洗机组号
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| id | 主键,自增 |
|
||
| code | 零件号(如 B02858),全局唯一,工单选择零件号时显示的选项值 |
|
||
| productTypeId | 所属毛坯号(关联 product_type.id),与现有工件分类体系保持一致,**此主键ID是所有其他设备(CNC、去毛刺等)识别工件类型的依据,不可改变** |
|
||
| washerGroupNo | 高压清洗机组号(1~9),即写入 FANUC 宏变量 #666/#888 的值;仅高压清洗机使用,其他设备忽略 |
|
||
| remark | 备注(可选) |
|
||
| createdAt | 创建时间 |
|
||
|
||
**新表 `work_order_part`(工单零件号表)**:存工单选了哪个零件号
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| id | 主键 |
|
||
| workOrderId | 工单ID(关联 work_order.id) |
|
||
| partNoId | 零件号ID(关联 part_no.id) |
|
||
|
||
**equipment 表**:高压清洗机记录(ID=5)的 `ipAddress` 字段值 = FANUC 连接地址,格式 **`IP:端口`**(如 `192.168.x.x:8193`),**不写死端口**,生产提供后整串填入;端口默认 8193,但以数据库实际配置为准。
|
||
|
||
### 2. 前端(新建工单弹窗)
|
||
|
||
现有选择是两级:`种类 → 毛坯号`([work-order-editor/index.tsx](frontend/src/components/work-order-editor/index.tsx) 的 Select 分组)。
|
||
|
||
改为三级:`种类 → 毛坯号 → 零件号`,样式不变,多一层显示,用户选择零件号后随工单一起提交。
|
||
|
||
### 3. 后端
|
||
|
||
**新增 FANUC 通讯模块**(替换现有 `internal/cnc/` 的 stub):
|
||
- 使用公用库 `bjhardman.cn/bjhardman/gofocas`(与 goplc 同仓库,已有权限)
|
||
- 连接地址从 equipment 表 `ipAddress` 字段读取(格式 `IP:端口`,如 `192.168.x.x:8193`)
|
||
- 提供写宏变量方法:`SetMacroVar(addr, macroNo, value)`,即写 #666/#888
|
||
|
||
**清洗机调度流程修改**([washer_orchestrator.go](internal/processor/eventloop/washer_orchestrator.go)):
|
||
- 放料动作前插入"查零件号 → FANUC 写 #666/#888"
|
||
- 卸载逻辑取消换料(exchange),改为两个槽位都完成后再逐个取出
|
||
|
||
**新建工单逻辑修改**([create_work_order_logic.go](internal/logic/workorder/create_work_order_logic.go)):
|
||
- 接收并保存零件号到 `work_order_part` 表
|
||
|
||
### 4. 种子数据(追加到 doc/data.sql)
|
||
|
||
19 条 `part_no` 记录(映射关系见第二节表格,数据已核对)。
|
||
|
||
## 四、实施顺序(确认后按此执行)
|
||
|
||
1. 拉取 gofocas 库,确认其 API(写宏变量的方法签名)
|
||
2. 数据库:新增 part_no、work_order_part 表 + 种子数据
|
||
3. 后端:FANUC 通讯模块封装
|
||
4. 前端:工单选择增加零件号层级
|
||
5. 后端:清洗机流程接入 FANUC 写入 + 取消换料
|
||
6. mockrun 验证(gofocas 用 mock 模拟)
|
||
|
||
## 五、待确认事项
|
||
|
||
1. ✅ **gofocas 库**:与 goplc 同仓库,有权限可拉取,实施时直接 `go get`
|
||
2. **FANUC 连接地址**:生产提供高压清洗机 CNC 的 `IP:端口`(端口默认 8193),填入 equipment.ip_address,先留空
|
||
3. ✅ **一个工单只选一个零件号**:已确认,工单内所有工件同一零件号
|
||
4. **说明**:本方案只**追加**新表/新数据,不修改 signals.sql 及现有信号(StartMeasure 等在 signals.sql 中保持不变)
|
||
|
||
---
|
||
|
||
## 六、代码示例(放文档底部,仅供确认,不直接改代码)
|
||
|
||
### 1. 种子数据 SQL(追加到 doc/data.sql)
|
||
|
||
```sql
|
||
-- 零件号表(含清洗机组号)
|
||
CREATE TABLE IF NOT EXISTS part_no (
|
||
id SERIAL PRIMARY KEY,
|
||
code VARCHAR(20) NOT NULL UNIQUE,
|
||
product_type_id INT NOT NULL REFERENCES product_type(id),
|
||
washer_group_no INT NOT NULL,
|
||
remark VARCHAR(255) DEFAULT '',
|
||
created_at TIMESTAMPTZ DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE part_no IS '零件号表(高压清洗机按零件号分9组程序)';
|
||
COMMENT ON COLUMN part_no.id IS '主键,自增';
|
||
COMMENT ON COLUMN part_no.code IS '零件号(如 B02858),全局唯一,工单选择零件号时的选项值';
|
||
COMMENT ON COLUMN part_no.product_type_id IS '所属毛坯号(关联 product_type.id),与现有工件分类体系一致,此主键ID是所有设备(CNC、去毛刺等)识别工件类型的依据,不可改变';
|
||
COMMENT ON COLUMN part_no.washer_group_no IS '高压清洗机组号(1~9),即写入 FANUC 宏变量 #666/#888 的值;仅高压清洗机使用,其他设备忽略';
|
||
COMMENT ON COLUMN part_no.remark IS '备注(可选)';
|
||
COMMENT ON COLUMN part_no.created_at IS '创建时间';
|
||
|
||
-- 工单零件号关联表
|
||
CREATE TABLE IF NOT EXISTS work_order_part (
|
||
id SERIAL PRIMARY KEY,
|
||
work_order_id INT NOT NULL REFERENCES work_order(id),
|
||
part_no_id INT NOT NULL REFERENCES part_no(id),
|
||
created_at TIMESTAMPTZ DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE work_order_part IS '工单零件号关联表(一个工单只选一个零件号)';
|
||
COMMENT ON COLUMN work_order_part.id IS '主键,自增';
|
||
COMMENT ON COLUMN work_order_part.work_order_id IS '工单ID(关联 work_order.id),一个工单只对应一个零件号';
|
||
COMMENT ON COLUMN work_order_part.part_no_id IS '零件号ID(关联 part_no.id)';
|
||
COMMENT ON COLUMN work_order_part.created_at IS '创建时间';
|
||
|
||
-- 种子数据(19个零件号,对应9组)
|
||
INSERT INTO part_no (code, product_type_id, washer_group_no) VALUES
|
||
('B02858', 1, 1), ('B20044', 1, 1), ('B20223', 1, 1), ('B20480', 1, 1),
|
||
('B20177', 1, 2), ('B20248', 1, 2), ('B20538', 1, 2),
|
||
('B20227', 2, 3), ('B20257', 2, 3),
|
||
('B20141', 3, 4),
|
||
('B20061', 3, 5), ('B20235', 3, 5),
|
||
('B02943', 3, 6),
|
||
('B20149', 3, 7),
|
||
('B20240', 4, 8),
|
||
('B02533', 5, 9), ('B02681', 5, 9), ('B20102', 5, 9), ('B20144', 5, 9);
|
||
|
||
-- 高压清洗机 FANUC 连接地址(格式 IP:端口,如 192.168.x.x:8193;待生产提供,先留空)
|
||
UPDATE equipment SET ip_address = '' WHERE id = 5;
|
||
```
|
||
|
||
### 2. FANUC 通讯模块(internal/cnc/ 替换 stub)
|
||
|
||
```go
|
||
package cnc
|
||
|
||
// 写 FANUC 宏变量(如 #666、#888)
|
||
// gofocas 库 API 以实际拉取到的版本为准,这里先画结构
|
||
// 连接地址从 equipment.ip_address 读取,格式 "IP:端口"(如 192.168.x.x:8193),端口不写死
|
||
|
||
type Client struct {
|
||
addr string // equipment.ipAddress,格式 "IP:端口"
|
||
}
|
||
|
||
func NewClient(addr string) *Client {
|
||
return &Client{addr: addr}
|
||
}
|
||
|
||
// WriteMacro 写宏变量,如 WriteMacro(666, 1)
|
||
func (c *Client) WriteMacro(ctx context.Context, macroNo int, value int) error {
|
||
// 解析 addr 为 host:port,调用 gofocas 库:连接 → 写宏变量 → 断开
|
||
return nil
|
||
}
|
||
```
|
||
|
||
### 3. 清洗机放料流程(washer_orchestrator.go 改动点)
|
||
|
||
```go
|
||
// 放料动作前:写 FANUC 宏变量
|
||
// 伪代码,具体以现有 buildWasherLoadActions 结构为准
|
||
for _, act := range actions {
|
||
if act.Kind == "load_to_machine" && act.MachineID == WASHER_HP {
|
||
// 1. 查零件号
|
||
partNo := queryWorkOrderPart(act.JobID)
|
||
// 2. 查组号
|
||
groupNo := partNo.washerGroupNo
|
||
// 3. FANUC 写宏变量(slotNo=1 写 #666,slotNo=2 写 #888)
|
||
fanuc.WriteMacro(ctx, 666, groupNo) // 左
|
||
fanuc.WriteMacro(ctx, 888, groupNo) // 右
|
||
// 4. 再走现有 PLC 放料
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. 前端三级选择(work-order-editor/index.tsx 改动点)
|
||
|
||
```tsx
|
||
// 现有:种类 → 毛坯号(两级)
|
||
// 新增:毛坯号 children 下再加零件号一层
|
||
// 数据来源:listProductTypes 接口扩展返回 partNos 数组
|
||
// 提交时:productTypeId + partNoId 一起传给 createWorkOrder
|
||
```
|