做设备销售的朋友应该都有这个痛点:整机几十万发出去,客户说好分期付,结果第二期就开始拖。你这边又是延长账期、又是派人催款,货已经装在生产线上,再拆回来成本高得离谱。我这两年给几家设备厂做的方案里,最被认可的一版,就是在信捷PLC里做了一套“分期付款到期锁机+动态解锁码”的功能:到期没收到款,机器按约定停机;客户付款后,厂家发一个当期有效的解锁码,输入之后设备恢复运行,下一期到期前再继续。这套系统的核心不在于把授权码做得多么复杂,而在于把业务闭环、设备安全和现场可用性组合起来。
这篇文章把这套方案从需求梳理、程序设计、动态解锁码生成,到防破解配置、跨型号移植,再到现场调试踩坑,完整写一遍。适合设备制造商的电气工程师、方案集成商、以及想给自己的非标设备加回款保障的开发者参考。不吹牛,这套东西我已经在两个系列的产品上跑了一年多,稳定性比预想的要好。
1. 先想清楚业务账:为什么要把分期付款逻辑写进信捷PLC
1.1 业务本质:把“设备控制权”当作合同履约的保证金
分期付款锁机的本质,不是技术问题,是商业问题。设备商把设备发出去,产权在形式上已经转移,但货款还没收完。这时候设备商手里还有什么筹码?最有效的筹码,就是对设备运行状态的控制权。如果设备本身具备“未按期付款就停机、付款后立即恢复”的能力,客户在催款电话打过来之前,其实已经先被设备提醒了。
我接触过的设备厂,做这套需求的分两种。一种是被拖欠货款逼出来的,另一种是产品规划阶段就要做租赁模式。前者的程序往往写得很急,后者的方案则更有余量。不管哪种,底层逻辑都一样:把“合同履约状态”映射成PLC内部的一组状态位和到期时间,设备根据这个状态决定是正常运行,还是逐步降速、报警、停机。
1.2 三种典型场景:分期销售、整机租赁、内部按产量结算
分期销售是最大宗的场景。客户签了12期或24期付款协议,每期到期日就是PLC里“下一次授权截止日”。收到当期款,厂家客服远程算一个解锁码发给客户,客户在触摸屏输入,设备继续跑一个月或一个季度。
整机租赁场景更彻底。设备是租给客户的,按月或按小时计费。这时候PLC里不仅要管日历到期,还要管累计运行时间。比如租赁费按500小时一结算,PLC就统计掉电保持区的累计运行时间,到500小时停机,付费后解锁下一个500小时。
还有一种内部结算场景,在同一个集团工厂里很常见。不同部门共用一条产线,但成本要分摊到使用方。生产部们就要求在PLC里做一个产量计数器加到期锁,到预定的产量批次就停线,等结算单走完再解锁下一个批次。这个场景和分期付款本质相同,只是“期数”变成了“产量区间”。
1.3 为什么锁机逻辑要放在PLC这一层,而不是触摸屏或云平台
我见过不少方案把锁机做在触摸屏上,比如HMI里设一个到期时间,到期后HMI跳出一个密码输入框。这个方案的漏洞很明显:触摸屏是可以换的。客户把屏换掉,或者恢复出厂设置,锁机逻辑就没了。而且触摸屏的程序读取门槛相对低,稍微懂点HMI组态的人都能把密码页面绕过。
云平台锁机也有问题。很多设备在现场根本不在线,尤其是食品厂、化工厂的一些工段,处于内网或物理隔离状态。云平台到期锁机一旦离线就失去作用,或者反过来,离线时不该停机却停机了,售后电话被打爆。
PLC是设备控制的核心,藏在电柜里,有程序加密保护,替换成本最高。更重要的是,PLC直接控制执行机构,是真正“拿得住”的那一层。锁机逻辑放在PLC里,触摸屏只是一个输入窗口,即使屏被换掉,PLC依然在执行锁定动作。触摸屏没电、断线、被换,都不影响锁机功能的存在。这个选择,是整套方案的第一条设计原则。
2. 信捷PLC实现锁机的底层资源盘点:时钟、掉电保持区和程序加密
2.1 万年历时钟与掉电保持区是整套方案的基石
信捷的多数PLC都内置万年历时钟,掉电后由板载电池维持。没有这个时钟,分期付款锁机根本做不了。时钟读取指令在编程软件里直接调用,能拿到年、月、日、时、分、秒六个数据。锁机逻辑只需要比对“当前日期”和“授权截止日期”。
掉电保持区同样关键。PLC断电再上电时,普通寄存器D区数据会清零,而掉电保持区内的数据不会。我把“设备序列号、当前授权截止日期、累计运行时间、解锁状态标志”全部放在掉电保持区。这里要特别注意:不同信捷PLC系列的掉电保持区范围和容量不一样,做项目前第一件事就是翻手册确认。
2.2 程序加密与下载保护:保护你自己的源码
信捷PLC在编程软件里提供程序下载加密功能。下载程序时可以设置密码,后续上传、监控、修改都需要密码。这个不是我用来破解谁的锁,而是用来保护我们自己开发的程序,防止客户或者第三方维修人员把锁机逻辑直接从PLC里读出来。
说得直白一点,锁机逻辑写得再好,程序能被人随便上载走,那就等于白写。加密下载之后,程序内容不能随意查看,梯形图也不能被复制。这个功能是PLC出厂自带的合法能力,我们用它是为了保护自己软件的知识产权。这里也顺带提醒:如果你想拿这套思路去破解别家设备的锁机授权,不管技术上做不做得到,那都是侵权。
2.3 不同系列(XC/XD/XG)的资源差异与选型建议
信捷PLC的三大系列定位差异明显。我做过的项目,XC系列适合经济型纯逻辑设备,指令集精简,程序空间小一些,但做分期锁机这种轻量逻辑足够;XD系列是主流选择,程序容量大,支持浮点运算、多通讯口、高速计数,适合复杂工艺设备;XG系列面向中型设备,支持运动控制、CANlink总线扩展,适合多轴设备。
| 系列 | 定位 | 掉电保持区容量 | 程序容量 | 适合场景 |
|---|---|---|---|---|
| XC | 经济型 | 相对较小 | 精简 | 继电器柜、简单单机设备 |
| XD | 主流型 | 较充足 | 大 | 复杂单机、多工艺设备 |
| XG | 中型 | 充足 | 最大 | 多轴运动控制、总站设备 |
选型建议很直接:如果设备本身不需要太多IO和运动控制,就用XD系列把锁机逻辑和工艺逻辑合在一起;如果设备很大、工艺复杂,千万不要为了省成本把锁机功能硬塞进XC那样的小程序空间,程序挤成一团,后期维护会很难受。
3. 动态分期付款程序的设计思路:到期判断、期数推进与解锁流程
3.1 核心状态机:运行期、等待解锁期、停机期
整个锁机程序本质是一个三状态状态机。正常运行期:当前日期在授权截止日之前,设备自由运行。等待解锁期:当前日期已经超过授权截止日,但还给了客户一段缓冲时间,比如缓冲3天,期间设备正常运行,但触摸屏上会闪烁“授权即将到期”的提示。停机期:超过缓冲时间后,设备按设定动作停机,此时只有输入正确的当期解锁码才能恢复。
把状态位做成M寄存器,程序里每个工艺主流程都串联一个“运行允许”位。这个位为ON,设备正常动作;为OFF,设备不做关键动作。设计工艺时要注意,停机不要停得太粗暴。电机可以停,但急停不要联动;气缸最好回到安全位置;加热设备要先切断输出再提示冷却。我在现场见过因为锁机直接切断加热导致产品批量报废的情况,从那以后锁机动作一律设计成“先降输出,再停执行,最后报警”。
3.2 到期日如何计算与存储:用“截止日期”而不是“剩余天数”
有些工程师做这个功能时喜欢存“剩余多少天”,然后每次上电用实时时钟减掉。这种做法有一个坑:PLC里的时钟会掉电、会被手动改、会漂移,剩余天数一旦被改成999天,锁机就报废了。
我的做法是存“下一次授权截止日”,即一个具体的年月日。解锁码校验通过后,PLC直接把截止日改成“当前日期再加一个付款周期”,比如加30天、加一个自然月、加一个季度。程序里不需要做复杂的日期减法,只需要比较当前日期是否超过了截止日。这里还要注意月份天数的问题,日期推进最好放在解锁成功的那一刻,而不是放在每天运行的扫描周期里,否则月末月初容易出偏差。
3.3 解锁成功后如何推进期数:一次解锁只推进一步
动态分期付款的逻辑重点在“动态”二字。每个周期,PLC内部都维护一个“当前期数N”。客户输入解锁码时,PLC先判断这个码是不是“针对当前期数N”的解锁码,校验通过后,把期数N加1,同时把截止日推进到下一个周期的日期。
这样做的好处是防止一码多用。比如客户在第三期付了款,拿到第三期的解锁码,他不能用这个码反复解锁第四期、第五期。因为期数已经推进到4和5了,第三期的码只对应期数3。这跟酒店的电子钥匙逻辑一样:换一拨客人,换一套房卡,旧卡永远打不开新门。
3.4 与触摸屏的交互设计:输入授权码、显示状态与剩余天数
锁机程序写好后,客户现场的交互入口一般是触摸屏。我在触摸屏上做一个“授权管理页面”,显示三行信息:当前设备序列号、当前授权截止日期、授权状态。下面放一个数字输入框,用于输入解锁码。
这里有个细节容易被忽略:HMI脚本里尽量只做“把解锁码写入PLC的某个字符串寄存器”这件事,不要在触摸屏的宏指令里做任何校验逻辑。因为触摸屏的脚本是可以被部分工程师下载查看的,一旦宏指令里出现了算法或密钥线索,整套动态码系统就形同虚设。解锁码的校验必须全部放在PLC内部完成,触摸屏只是一个显示和输入终端。
4. 动态解锁码的生成与校验:不联网也能安全授权的关键
4.1 为什么用动态码而不是固定密码
固定密码是最容易翻车的方案。设备商图省事,在PLC里写一个固定的6位密码。客户之间只要互相通个气,密码一夜之间就传遍全行业,后面再想收款就难了。
动态码的思路是:解锁码和设备序列号、当前期数、密钥绑定。设备序列号每台机器唯一,期数每个付款周期都在变,所以每个解锁码只对“这台机器、这个周期”有效。哪怕两个客户交换了解锁码,也没法互相使用,因为序列号对不上。
4.2 解锁码算法设计:设备号、期数、密钥与校验位
拿一个实际的简化案例说。某设备合同是12期付款,PLC里写入设备序列号SN,比如8位整数。当前期数为N,设备厂内部保存一个密钥K。解锁码的计算思路是:把SN和N组合成一个数字,叠加上K,再做一次自定义置换和模运算,生成一个6位数字。其中前5位是有效信息,最后1位是校验位,用于PLC侧初步判断输入是否合法。
算法本身不需要是密码学级别的东西,因为PLC端每次校验都是离线、独立进行的,攻击者面对的是黑箱。关键是设备序列号必须参与计算,期数必须参与计算,密钥只有厂家内部知道。
4.3 厂家侧生成工具的实现思路
设备厂客服在收到客户付款后,需要在电脑上快速生成当期解锁码。我一般做一个简单工具,逻辑和PLC里的校验算法保持一致。
# 演示用动态解锁码生成工具的核心逻辑 # 实际项目中密钥不会明文写在脚本里 import random def gen_code(sn, period, key_seed): # 1. 组合基础数据 raw = sn * 10000 + period # 2. 叠加厂家密钥种子 raw = raw ^ key_seed # 3. 做一次数字置换 s = str(raw).zfill(12) shuffled = s[7:] + s[3:7] + s[:3] # 4. 取模生成6位码 code = int(shuffled) % 900000 + 100000 check = code % 7 return code * 10 + check print(gen_code(20240001, 1, 51873))这个工具可以做成Excel公式,也可以做成单独的小程序。客服输入客户设备序列号和当前期数,自动生成解锁码,通过微信或电话发过去。整个过程不需要联网验证,PLC和工具端各自独立运算,结果比对一致即解锁成功。
4.4 PLC侧校验逻辑:字符串比较、错误次数限制与防重放
PLC侧的逻辑是:触摸屏输入解锁码后,PLC按同样算法用当前序列号和当前期数算出一个“期望码”,和输入的码比较。相同则期数加一,截止日推进,写入解锁成功标志。
这里有几个必须做的细节。解锁失败要计数,连续错5次就锁住解锁页面30分钟,防止暴力试码。解锁成功后要把输入框清零,防止客户拿着旧码反复触发。每次解锁都往事件记录区写一条日志,包括解锁时间、解锁后的期数,这对接下来的售后纠纷处理非常重要。
5. 高安全性设计:防调时间、防清数据、防抄程序的实战配置
5.1 时间篡改检测:识别时钟回拨与时间跳跃
客户想把锁机绕过去,第一个想到的就是改PLC时钟。防这个,不能只靠“相信客户不会改”,要主动检测。
我在PLC里设计了三个检测维度。第一,上电时记录掉电保持区里保存的“上次关机日期”,如果当前时钟比上次关机日期还早,说明时间被回拨了,锁机标志直接置位。第二,记录上电时长,如果一次上电运行时长异常短,说明可能有人频繁断电改时间再上电搞测试。第三,把万年历时钟和“累计运行时间”做交叉验证,假设设备累计运行已经超过1000小时,而时钟显示距离出厂只有200天,明显不合理。
检测到时间异常后,不直接锁死设备,而是进入受限运行模式:允许设备慢速运行,不允许满速满负荷。这样做是因为有的客户并不是恶意,可能只是时钟电池坏了,时间重置了。如果直接锁死,售后处理会很被动。
5.2 掉电保持区数据冗余与校验和
掉电保持区的数据有一个风险:客户如果懂一点PLC,用编程软件把保持区数据清零,锁机状态就没了。应对办法是冗余交叉存储。
我把关键数据各存三份,分别放在三个不连续的保持区地址段。上电时检查三份数据是否一致,如果不一致,以多数一致的为准,并恢复异常的那份。同时对整个关键数据块计算一个校验和,校验和存到另一个固定位置。任何人手动改了数据区的任何一个数字,校验和就对不上,程序判断为“数据被篡改”,锁机标志置位。
这套冗余逻辑并不复杂,但很实用。因为我见过客户用编程软件在线修改保持寄存器值的操作,如果只存一份,客户改完直接越过锁机。存三份再带校验和之后,客户改一两个地址基本是徒劳的。
5.3 开机自检与误锁保护:宁可多报故障,不可误锁生产
高安全性还有一个反面,就是“别把自己人误锁死”。设备厂自己的调试工程师在现场调程序,改了系统时间,结果设备直接停机,这种乌龙我至少见过三次。
所以设计上要区分“硬锁”和“软锁”。收到款项后正常解锁是硬解锁;而时间异常、数据校验失败这类情况,程序只进入警告模式,触摸屏明确提示“联系设备厂家售后处理”。售后工程师用厂家专用的售后口令可以临时恢复运行,再通过正常流程刷新授权数据。这个售后口令与客户解锁码走完全不同的算法逻辑,只掌握在厂家自己手里。
5.4 程序保护策略:加密下载、操作权限分级与密钥分散
程序加密下载前面已经说了,这里补充两个重要细节。第一,PLC的密码不要只设一个,最好设操作密码和上传密码两个层级。操作密码用于现场日常修改,上传密码用于保护程序不被读走。密码不要用简单数字组合,建议用设备厂固定资产编号相关的长字符串。
第二,解锁算法里涉及的密钥一定不要以明文常量的形式写在梯形图里。可以拆成三段,分别存储在三个保持寄存器,或者通过几行异或运算在程序运行时动态组合。这样做主要防的是“程序被非授权人员监控时直接看到关键常量”。虽然信捷PLC加密后很难被上载,但多一层保护总没坏处。
6. 覆盖多种型号的移植方案:XC/XD/XG程序框架复用
6.1 用功能块与子程序抽象业务逻辑
锁机逻辑应该在PLC程序里做成独立子程序,和工艺主程序分开。我在做第一个XD系列项目时就把锁机程序写成一个完整的子程序段,输入参数只有三个:当前日期、设备序列号、输入的解锁码。输出参数有两个:运行允许位、状态提示码。主程序只需要调用这个子程序,根据运行允许位去控制设备动作。
这样做最大的好处是移植。从XD移植到XG,工艺程序可以不动,锁机子程序只要把指令改成目标系列的对应指令。如果当初把锁机逻辑和工艺逻辑揉在一起写,换一个型号等于整个程序重来。
6.2 寄存器地址映射表:一个型号配一张表
不同系列的掉电保持区范围、M区大小、定时器编号规则都有差异。我把锁机程序用到的主要寄存器做成一张映射表,每移植一个系列就先对照手册核对一遍这张表。
| 数据项 | XC系列 | XD系列 | XG系列 |
|---|---|---|---|
| 设备序列号 | 保持D区低段 | 保持D区低段 | 保持D区低段 |
| 截止日期 | 保持D区中段 | 保持D区中段 | 保持D区中段 |
| 当前期数 | 保持D区中段 | 保持D区中段 | 保持D区中段 |
| 状态标志 | M区指定区间 | M区指定区间 | M区指定区间 |
| 校验和 | 保持D区高段 | 保持D区高段 | 保持D区高段 |
这张表做完之后,移植就是机械操作。我在实际项目中曾经因为没核对保持区范围,把数据写进了普通D区,结果一断电全部清零,客户第二天起来发现设备锁死了。从那以后,移植之前第一件事永远是查手册,没有任何捷径。
6.3 触摸屏与通讯变量统一命名
触摸屏和PLC通讯的变量,我把命名规范化:SN_DEVICE、DUE_DATE、PERIOD_NUM、UNLOCK_CODE、RUN_ALLOW、LOCK_STATUS。这些命名在XC/XD/XG各系列工程里保持一致。触摸屏程序做一次,后面换系列只需要重定设备地址,画面逻辑几乎不用改。
命名这块千万不要图省事用中文。我见过用中文注释和中文变量名的工程,屏幕上显示没问题,但程序一加密下载,触摸屏变量同步经常出乱子。统一用英文加下划线,后期维护和跨工程复用都省心。
6.4 实测移植的遗漏点:指令差异、文本屏差异与数据格式
信捷不同系列在指令上会有一些细微差异,比如某些字符串比较指令、取整指令的写法不一致。另外,经济型设备上如果配的是文本屏而不是触摸屏,解锁码输入界面会简陋很多,通常只能通过增减数字按键逐位输入。这时候解锁码尽量控制在6位数以内,太长的话客户在文本屏上输码会输到崩溃。
还有一个非常容易被忽略的是数据格式。XC系列有些寄存器按BCD格式处理,触摸屏默认显示十进制。只差这么一下,客户的解锁码明明是正确数字,PLC收到的却是另外一组二进制值,校验永远失败。这个问题我在现场花了整整一个下午才定位到,从那以后,数据格式总是写进映射表,每次移植时单独检查。
7. 调试与交付:我在真实现场踩过的坑
7.1 调试时把自己锁死了:预留售后解锁入口
我自己的一个项目,调试阶段修改了PLC时钟来模拟故障场景,改完忘了改回来,第二天设备上电直接停机。当时还未完善售后解锁逻辑,只能重新下载程序,现场的工人等着开工,压力非常大。后来我专门加了一个售后解锁入口,这个入口不对外公布,平时是隐藏功能。
这个售后解锁入口的逻辑是:记录当前期数,用厂家密钥单独算一个“调试期解锁码”,输入后设备运行一整天,方便现场调试。特别是带锂电设备的客户,一条线停机一个小时损失很可观,多一个应急手段,现场的局面完全不同。
7.2 用户改时钟、换PLC导致的误锁案例
真实遇到的一个案例,客户现场供电不稳定,PLC频繁掉电,板载时钟电池又刚好没电了。每次上电时钟停在出厂默认值,而掉电保持区里的截止日期是正常日期。程序判断当前日期远小于截止日期,技术上讲不应该锁机。但因为我把“上次关机日期”存在保持区,而使用过程中时钟跳回了默认值,触发了我设定的时间回拨保护,设备进入警告模式。
后来我加了逻辑:如果检测到时钟明显小于保持区里的“最低历史日期”,且电池电压异常时,先提示更换电池,不直接锁机。这个调整之后,误锁电话基本就绝迹了。
7.3 现场没有电脑也没有屏,如何查看锁机状态
不是所有设备都有触摸屏,有些小设备只有几个按钮和指示灯。这时候为了定位问题,我会让PLC在故障时通过输出指示灯闪出特定频率。比如锁机状态是“运行允许”指示灯慢闪3次停1秒;时间异常是快闪5次停2秒;数据校验失败是持续快闪。维修电工只需要看LED灯闪烁规律,就能上报给厂家售后。
这个思路很土,但特别管用。电工师傅不用带电脑,看一眼灯就能判断是哪一类问题。比让客户拍照发微信快得多。
7.4 交付清单与培训:给销售和客服的FAQ
系统上线前,我给设备厂销售和客服做过一份FAQ文档。内容包括:客户说锁机了怎么办?如何确认客户设备序列号?收款后如何生成解锁码?解锁码发过去客户说不对怎么办?这些问题虽然很简单,但客服在电话里往往是懵的,一套标准流程能省很多时间。
同时文档也写明白了一条:锁机不是用来跟客户对赌的,它只是合同履约的工具。客户正常付款,系统就正常运转;客户有纠纷,销售要第一时间介入,而不是让客服在电话里跟客户扯皮。技术手段终究要为商务关系服务,这一点比任何代码都重要。
8. 写在最后:这套方案的边界与生存法则
做这套方案最大的体会,是不能沉迷于“把客户防死”。设备厂和客户是长期合作关系,锁机系统只是回款保障的底线,不是压迫客户的工具。真正专业的做法是:设计一个让正常客户无感的系统,设备正常运行,到期前有提醒,付款后立刻解锁,而对恶意拖欠或暴力改机的客户,系统能稳稳地守住底线。
技术上的安全性也要有清醒认识。任何PLC锁机系统都不能做到绝对不可破解,因为PLC本身是通用可编程设备,程序理论上都存在被逆向的可能。想让解锁码机制运转得好,核心思路不是算法多高深,而是“设备绑定+期数动态变化+多次尝试限制+程序加密”这套组合拳。破解成本一旦高于剩余货款,这个方案就成功了。
最后分享一个小技巧:我在所有项目里都会把锁机逻辑和工艺参数彻底分开。工艺参数存放在另一组寄存器区,锁机程序只判断“是否禁止运行”,绝不去修改任何工艺数值。这样即使触发了锁机,客户也不会因为数据被改而投诉。把锁机这件事做得越“干净”,设备厂和客户之间的信任就越不容易被破坏。这套方案说到底,是给设备加一道安全阀,而不是给客户加一道枷锁。