起因

收官篇写到跟客户的系统对接,一段装不下,只立了个骨架:主动上传、被动查询、反向触发三个方向。这块值得单独展开——它是很多做设备的程序想不到、到了现场才吃亏的地方。客户的现场除了我们的机器,还有主控系统和一堆外围:扫码的、称重的、贴标的、打印的,全在一张网上。机器在里头是一个节点,不是一座孤岛。这篇把这个节点对外怎么说话写全。

往外送什么

客户那套系统,MES 也好 WMS 也好,要的不是图,是结构化的记录。每件一条:什么时候抓的、条码是什么、结果码是什么、放去了哪个格口;再加周期汇总:班次产量、首抓率、失败类型分布、稼动率。报警也分级上报:提示级的攒着随日报送,警告级的立刻推,停机级的一秒内到——客户值班的人按级别决定看不看。

上报在业务层做,不碰实时层,1kHz 循环里没有网络这个概念。事件先进本地队列落盘,网络断了先攒着,通了续传,车间网络断半天,一条记录不许丢。时间戳用机器自己的钟打,机器跟客户的主控对时——不然两边的日志对不齐,出了事回放的时候,两套时间各说各话。

客户来问怎么答

被动查询是第二个方向:客户的系统随时连上来问状态、要历史。协议跟客户走,Modbus TCP、TCP 报文的 API、Web 接口、数据库中间表都做得到——这层写成适配器,机器内部的事件格式只有一种,往外才翻译成各家要的样子。

Modbus 那头有讲究。寄存器分区排:状态区只读,机器的模式、当前节的进度、报警码,全映射在保持寄存器上;命令区只写,客户写进来的是启动、暂停、要状态;再放一个心跳寄存器,机器周期刷新,客户那边看着心跳停了就知道机器掉线了,不会把一台死机当成正常在跑。命令报文带序号,同一条指令重发不重复执行——网络这东西,重发是常态。

客户来指挥怎么接

第三个方向最容易被漏掉:反向触发。客户的系统来触发我们的动作——要看某件的高清单据照,发个指令过来,拍一张回传;要某个 IO 动一下联动外围设备,指令进来就执行;要启动暂停,也走这边。多数做设备的只想了往外送数据,把数据交出去完事;真到了现场,客户的主控要的是一个指挥得动的节点,不只是一个被喂的节点。

边界同时立好:客户能触发的是白名单里的动作——拍照、IO、启停、要状态;臂怎么动、轨迹怎么走,这个指令进不来。网络上的指令到业务层排队,过白名单这道门,到不了实时层。这条跟上报不碰 1kHz 是同一条规矩的两半:数据出不去实时层,指令也进不去实时层。

三个方向排在一起看:

方向 谁发起 典型用途 常见做法
主动上传 我们 事件、报警、周期汇总 推送到客户的消息服务
被动查询 客户系统 问状态、要历史 Modbus 寄存器、TCP 接口、Web
反向触发 客户系统 触发拍照、IO、启停 TCP 指令、Web

拍照留存

对接里有一块客户问得最多的:出了纠纷,这件是谁动的、当时什么样。答案是照片。

留存走识别相机,不另装专门的记录相机——理由很实际:追溯要的是机器看到什么、依据什么做的决策,识别前那帧原图就是证据本身;另装一台,角度光线都对不上,出了争议两张图互相矛盾,反而说不清。有个细节要抠住:存原图,不是存模型的输入——模型吃的是缩到六百四十的图,相机出来的是几百万像素,留档按原图存,面单上的字照得清楚才算证据。

拍照这件事本身也挂在接口上:我们自己的识别流程触发是主路,客户的系统要调一张高清单据照,反向触发那条路进来,一样拍、一样存、一样回传。失败的件多存几张,跟数据回流那套失败存图正好是同一条数据流。量不大:一张几十到两百 KB,一天几千件几 GB,滚动存三十天一块两 T 的盘绰绰有余。脱敏的规矩跟回流一样:图出仓先打码,客户在自己仓里调看不算出仓。

让对接的人好过

还有一条衡量的标准,看着软,其实是成熟系统的必要预留:客户那边的上位机工程师,写一点代码就能对接上。落到实处是四样东西。协议文档要人能读,寄存器表、报文格式、每个字段什么意思,一页一页写清楚,不让人靠抓包猜。示例代码要给全,连接、查询、订阅事件、触发拍照,十来行能跑通的那种,Python 一份 C# 一份。再给一个模拟器,上位机工程师不用等机器到场,在办公室对着模拟器把对接调通,到了现场只做最后验证。协议往后加字段,老版本照跑,别让客户调通的代码因为我们的升级重写一遍。

设备好不好,客户的主控工程师比谁都清楚——对接接得顺不顺,直接决定这套设备在他嘴里是什么评价。

收尾

机器干活的水平,是机器自己的事;机器在客户那张网上好不好相处,是对接决定的。三个方向的接口、白名单的边界、给对接人的文档和模拟器,这些做在前面,机器到了现场才不是多了一台设备,而是多了一个好相处的节点。等机器真落到客户的仓里,现场篇再回头看这篇列的东西哪些够用、哪些漏了。

参考链接