用 HSL 重构 PLC 通信,核心是把过去“一个品牌一套库、一套异常处理”的碎片化代码,统一为“一个OperateResult模式、一套读写 API”的标准化结构。
重构的核心:理解OperateResult模式
HSL 所有读写操作都返回OperateResult或OperateResult<T>。你不再需要 try-catch 包裹每一次调用,而是统一检查.IsSuccess:
varresult=plc.ReadInt16("DB100.2");if(result.IsSuccess){shortvalue=result.Content;}else{// result.Message 给出失败原因}这个设计让通信错误处理变得可预测,也便于在应用层统一封装重试逻辑。
重构案例:西门子 S7-1200/1500 视觉结果写入
以下是把之前 S7.NetPlus 的握手逻辑,重构为 HSL 实现的完整代码。
1. 连接管理类
usingHslCommunication;usingHslCommunication.Profinet.Siemens;publicclassPlcService{privateSiemensS7Net_plc;privatereadonlystring_ip;privatebool_connected;publicPlcService(stringip){_ip=ip;}publicOperateResultConnect(){// S7-1200/1500 机架0,槽1_plc=newSiemensS7Net(SiemensPLCS.S1500,_ip);varresult=_plc.ConnectServer();// 只调一次_connected=result.IsSuccess;returnresult;}publicboolIsConnected=>_connected&&_plc!=null;}关键约束:ConnectServer()不要放在定时器里反复调用。它内部会先关闭旧连接再重建,若此时有并发读写会引发异常。正确做法是启动时连一次,后续通过每次读写的IsSuccess感知连接状态。
2. 视觉结果写入(含握手)
假设视觉结果写入 DB100,内存布局为:
| 地址 | 类型 | 用途 |
|---|---|---|
| DB100.0 | Bool | ResultsValid(视觉→PLC) |
| DB100.1 | Bool | InspectionAck(PLC→视觉) |
| DB100.2 | Int16 | X坐标 |
| DB100.4 | Int16 | Y坐标 |
| DB100.6 | Int16 | 角度(×100) |
publicOperateResultWriteVisionResult(shortx,shorty,shortangle){// 批量写入结果数据varr1=_plc.Write("DB100.2",x);if(!r1.IsSuccess)returnr1;varr2=_plc.Write("DB100.4",y);if(!r2.IsSuccess)returnr2;varr3=_plc.Write("DB100.6",angle);if(!r3.IsSuccess)returnr3;// 最后置握手位return_plc.Write("DB100.0",true);}publicOperateResult<bool>ReadAck(){return_plc.ReadBool("DB100.1");}注意地址格式差异:HSL 的西门子地址写作"DB100.2",而非 S7.NetPlus 的"DB100.DBW2"。
3. 调用侧的握手流程
// 视觉检测完成后varwriteResult=plcService.WriteVisionResult(x,y,angle);if(writeResult.IsSuccess){// 等待 PLC 确认(循环检查 Ack)for(inti=0;i<10;i++){Thread.Sleep(50);varack=plcService.ReadAck();if(ack.IsSuccess&&ack.Content){// PLC 已读取,清零 ResultsValidplcService.Write("DB100.0",false);break;}}}批量读取与字节转换
对于需要读取连续地址的场景,HSL 提供Read返回byte[],再用ByteTransform按偏移解析,避免多次网络往返:
OperateResult<byte[]>read=_plc.Read("DB100",10);// 读20字节if(read.IsSuccess){shorttemp=_plc.ByteTransform.TransInt16(read.Content,0);shortpress=_plc.ByteTransform.TransInt16(read.Content,2);intcount=_plc.ByteTransform.TransInt32(read.Content,4);}重构后的结构性收益
相比之前的 S7.NetPlus 方案,HSL 重构带来三个实际变化:
1. 多品牌切换成本归零。若产线新增一台三菱 PLC,只需把SiemensS7Net换成MelsecMcNet,读写方法名和OperateResult检查逻辑完全一致。
2. 异步支持原生可用。HSL 提供ReadAsync/WriteAsync,返回Task<OperateResult>,便于在视觉上位机中与async/await流水线集成。
3. 错误处理统一化。不再需要为每个品牌的异常类型写不同的 catch 分支,所有通信失败都通过IsSuccess和Message表达。
需要注意的实操约束
优化块访问问题不变。HSL 的SiemensS7Net同样基于绝对地址寻址,TIA Portal 中的目标 DB 块仍需取消“优化的块访问”。
不要用 ConnectServer 做心跳检测。由于它内部会重建连接,应与读写操作互斥。连接状态直接通过读写结果判断即可。