点位录入别再手敲:三条路,共用同一套结果契约
📚 MES 集成商系列 | 写给做选型与交付决策的人
采集项目里最枯燥、也最容易出错的一段,是把点位录进网关。
本系列 02 篇的工期表里,这一段是按"每小时多少个点"报的——快的 200 个/小时,慢的 30 个/小时。一个五千点位的项目,光录入就是小半个月。
网关给这件事准备了三条路。这篇讲它们各管哪一段,以及它们共用的一套约定——那套约定才是让"几千个点位"这件事从"手工活"变成"跑一遍"的关键。
gitee(主仓库):https://gitee.com/wang4856304/iot-gateway
github:https://github.com/Ellisata/iot-gateway(AGPL-3.0 开源)
一、先算这笔账
手敲点位慢,这一点都知道。但真正贵的不是慢。
贵在"敲错了不会报错"。 点位地址写错一位——%MW100 写成 %MW10——那个点位从此永远取不到值。而它并不会让采集停下来,也不会让设备离线:它只是安静地一直没值。这类错误往往要到客户对账时才被发现,那时点位已经上线跑了几周。
时间账,用 02 篇的估算基准算:
| 点位表齐全、地址规整 | 50~200 点/小时 | 25~100 小时 |
| 需要现场逐个确认地址 | 10~30 点/小时 | 160~500 小时 |
第二行才是现场常态——客户给的点位表往往不全,缺的那些要现场对着设备确认。
📌 所以这篇文章要省的不只是工时。它同时消掉了"地址写错"这一类错误——因为地址不再经过人手。
二、三条路,各管一段
| 设备扫描 | 设备还没建,只知道它在哪个网段 | 一批设备(可勾选一键建) |
| 点位扫描 | 设备已建好,要摸清它上面有哪些点位 | 一批候选点位(可勾选一键建) |
| Excel 导入 | 手上已有一份整理好的点位表 | 设备或点位,按表建 |
三条路看起来是三件事,但它们背后的建库动作是同一个——一样的结果契约、一样的逐行校验。这一点在第六节展开。
三、第一条路:设备扫描——“这个网段里谁在”
扫描页的模型很朴素:你选协议、选网段,网关把网段里每个地址问一遍。
这里有一条职责边界值得记一笔:
网关负责规划和调度,插件只回答一个问题——“你给我的这个 IP:端口,是不是我的设备。”
网关枚举本机网段、把网段展开成一个个主机地址、控制并发、限速、统计进度、支持取消;插件只做那一次探测。这意味着"扫一个网段"这套机制是被所有支持扫描的协议共用的,协议之间只在"探测用哪种报文"上有差别(比如 EtherNet/IP 用 ListIdentity、FINS/UDP 用节点查询)——而这些差异都封装在各自的插件里。
几处现场会碰到的限制:
- 只扫本机所在的网段。 不接受任意网段——否则这台网关就成了一个通用端口扫描器。
- 目标数有上限。 一个 /16 展开是六万多个地址,默认只扫前 1024 个。超限时页面必须明确告诉你"只扫了前 N 个"——不显示的话,你会从"没扫到设备"得出"这个网段没有设备",而这两个结论的下一步动作完全相反。
- 站号默认只探 1 号站。 现场设备若不是 1 号站,要在扫描参数里显式写。
- 串口协议不参与。 探测的目标模型是"IP:端口",表达不了"COM 口",所以这类协议不会出现在扫描页的下拉里。这是设计如此,不是缺功能。
- 扫描任务只在内存里。 网关重启就没了,过期后也会被清理。重新扫一次即可。
四、第二条路:点位扫描——“这台设备上有哪些点位”
这一条是本篇最需要说清的一条,因为它的产出很容易被误解。
先看方向:它和设备扫描是相反的两件事。
| 问的是 | 网段里谁在 | 这台已存在的设备上有哪些点 |
| 目标由谁定 | 网关(枚举网段) | 那台设备的 deviceId |
| 会话 | 无会话,一次一个目标 | 复用那台设备的采集会话 |
| 能不能取消 | 能 | 不能 |
它产出的是"候选清单",不是点位表
这是这一节的核心,也是整个功能里最容易被误读的地方。
设备不会告诉你它有哪些点位。
扫描做的事,是把那一段地址挨个读一遍,能读回来的列出来。所以它给出的是"这段范围里读得到的地址"——一份候选清单,不是一份可以直接用的点位表。
三处由此而来的性质:
① 值为 0 的点位默认不显示,但不代表它们不存在。
插件侧刻意不做零值过滤——原因很实在:在一台寄存器全是 0 的设备上过滤,会返回一个空列表,用户会以为"这里没有点位"。所以过滤放在界面上,做成一个「显示 0 值」的开关,由你决定要不要看。
② 地址列是只读的。
扫描结果里的地址(%MW100、D100、02010100)不给你在结果表里直接改。原因就是本文开头那笔账:写坏一个地址,那个点位永远取不到值,而且只报"地址无效"。**候选清单不该变成一个可以顺手改坏的输入框。**要改地址,去点位编辑页正式改。
③ 扫描结果有三种"没搞完",含义完全不同。
它返回三个计数和几个标志,别混着看:
| scanned / readable / unreadable | 试了多少、读回来多少、读不到多少 |
| truncated | 达到单次上限,后面的地址根本没试 |
| incomplete | 预算耗尽,范围还没扫完——与"读不到"是两回事 |
| warning | 中途断了,手上这份是跑了一半的结果——但它是可用的,可以照常建点位 |
incomplete 和"读不到"一定要分清:前者是"没问完",后者是"问了没答"。把它们合并显示,用户会以为后半段设备里没有点位。
⚠️ 一段扫描要花多久,看的是一个被钳过的值。 插件会自报一个预算(Modbus 报的是 20 秒),但网关几乎总会把它钳得更小(实际生效 7 秒)——因为这是一条同步 HTTP 链路,网关得保证自己停得下来。界面显示"大约要等多久"时用的是实际生效值;如果用插件自报的,你会去怀疑设备和链路,而根因在网关侧。
五、第三条路:Excel 导入——“我这份表已经整理好了”
如果客户给了点位表,这条路最直接。两张模板分开:设备导入表和点位导入表,都在页面上可以直接下载。
它和扫描那两条路的关系是:扫描负责"把设备里的东西掏出来",Excel 负责"把外部的表灌进去"。两条路的方向相反,但汇到同一个建库动作上——也就是下面这套约定。
六、三条路共用的一套约定
这是本文最想讲的部分。四条入口——扫描建设备、扫描建点位、Excel 导入设备、Excel 导入点位——返回的是同一个类型:
{ "total": 100, "success": 97, "failed": 3,
"errors": [ { "row": 12, "name": "%MW100", "reason": "该地址已存在", "code": "" } ] }
这个形状在仓库里还有第五处:批量上传插件。它没有复用这个类型,而是自己声明了一份同形的——因为它属于另一件事(插件安装,不是数据导入)。但对前端而言,这两者是同一类交互:批量提交 + 逐项成败明细。所以形状一致、类型分开,各自还能长出自己需要的字段。
这套约定里有几条设计,值得逐条说。
① 逐条失败,不中断整批
一批五千行里有三行有问题,剩下 4997 行照建,三行单独报给你。部分成功是预期行为,不是异常。
反过来的做法(一行错就整批退回)在现场几乎没法用:你会陷入"改一行、重传、又发现另一行"的循环,而每一次重传都是一次完整的上传。
② "硬失败"和"软提示"是两回事
失败的明细分两类,区别只在要不要用户确认:
- 硬失败——撞名、协议行缺失、连接配置不合法。重试也不会变,用户得去改。
- 软提示——扫描地址与库里另一台设备相同。用户确认后带上一个确认标志重提,就能建成。
第二类为什么不做成硬拦截?因为"同一个地址"在有些现场是合法的(比如同一台 PLC 从两个网口接)。系统没有资格替用户判断这件事,它只能提示。
📌 这背后是一个更一般的取舍:判重表在事务外读、事务内边建边补,所以它只是提示而不是判据——两个并发的建库请求理论上可以都通过这道检查。这是有意的:既然重复本来就允许用户确认后放行,就不该有唯一索引兜底去把它变成一条硬规则。
③ reason 给人看,code 给程序判断——不能用一个
失败明细里除了给人看的原因文本,还有一个可选的稳定标识码。
为什么要两个?因为原因文本会随文案和语言调整而变。如果客户端拿这段文本来做判断,那就是拿一个会变的东西当契约——改一次措辞,客户端的判断逻辑就静默失效了,而且不会有任何报错。
所以两者的分工是明确的:
- code 只用于分辨——它只有"需要客户端特殊处理"的那几种失败才有值(上面那个"地址重复、可确认放行"就是唯一一个);
- 展示一律走 reason。
💡 反面就是"在界面上枚举 code"——那等于把"给程序分辨"和"给人看"两种职责混成一种,两边都做不好。
④ 建库用的连接配置,服务端不采信客户端
扫描建库时,新设备的连接参数(地址、端口、站号)由服务端从自己持有的扫描任务快照里取,不接受客户端传上来的值。
理由:那是跨信任边界的数据——它决定网关接下来去连哪个地址。而任务快照本来就在服务进程里,没有理由让一段可能被改过的请求体来决定它。
而且即便取到了,也要再验一遍格式——插件给的东西同样不能被假定为合法。
⑤ 校验规则只有一份
"从扫描建设备"和"从 Excel 建设备"用的是同一个逐行校验函数。
这不是为了少写代码,是为了一致性:两处各写一份,早晚会对同一份数据给出不同判定——而表现出来的症状是"同一个点位,从扫描建能过、从 Excel 建过不了",极难解释。
七、项目地址
- gitee(主仓库):https://gitee.com/wang4856304/iot-gateway
- github:https://github.com/Ellisata/iot-gateway
项目以 AGPL-3.0 开源。
📌 关于本文的能力边界,如实说明:
- 扫描是"能读到就列出来",不是"设备告诉你它有哪些点位"。 这一点在界面上反复写,因为它直接决定你怎么用这份结果——它是一份候选清单,标签(中文说明)和业务语义仍然要人来填。三条路省掉的是"抄地址",不是"理解这些地址是什么"。
- 扫描只覆盖本机网段,跨网段要分别在各自网段的网关/主机上扫。
- 点位扫描不可取消,一次扫描会占用设备的采集会话一小段时间;串口设备尤其要考虑这一点。
- 三条路都改变不了 04 篇那条底线:地址写错的后果仍然由点位自己承担(该点位标记为地址无效,其余点位照常采集,设备保持在线)——扫描只是让这个错误更少发生。
本系列:
- 01 ·《做 MES 集成的都懂:PLC 采集不难,难在每个项目重来一遍》
- 02 ·《接一个采集项目,工期该报几天?》
- 03 ·《这个点位规模,网关扛得住吗?——投标前的容量估算》
- 04 ·《开源网关交付给客户,我会被要求开源吗?》
- 05 ·《RS-485 挂 20 台电表,为什么总是读不全?》
- 06 ·《工业数据采集项目验收清单》
- 07 ·《多厂区复制:一套模板交付四个工厂》
- 08 ·《老设备改造场景集:拿到一台十年前的老设备,数据怎么接?》
- 09 ·《采集网关的四种路线:把授权成本算清楚》
- 10 ·《协议驱动真机验证清单:哪些上过真机,哪些还没有》
- 11 ·《数据没上去?从上位机到 MES 的七段排查》
- 12 ·《项目交付后,怎么把自己摘出来》
- 13 ·《采集项目的合同,该写死哪几件事》
- 14 ·《客户掏出一台没人认识的设备:专有协议,现在能自己写驱动了》
- 15 ·《设备台账怎么进 MES:接口现成,但别用翻页去取》
- 16 ·《点位录入别再手敲:三条路,共用同一套结果契约》← 当前
网硕互联帮助中心




评论前必须登录!
注册