
简介这是一套基于Qt框架开发的西门子S7-1200 PLC上位机通信源码面向工业自动化领域初/中级开发者及高校相关专业学生解决OPC UA协议下与PLC实时数据交互、状态监控与可视化控制等典型工程需求。资源包共27个文件涵盖7个头文件含OPC UA客户端核心逻辑与UI组件定义、6个C实现文件含OpcUaClientByQT主类、波形图绘制、指示灯状态管理等、5张设备状态图标红/黄/绿/蓝/灰以及UI界面文件、项目配置文件.pro/.sln、静态库.a与动态链接库.dll等关键构建要素整体仅376KB轻量易集成。已有2144人学习下载代码结构清晰模块职责分明主窗口封装OPC UA连接与订阅逻辑wavechart与smoothcurvecreator支持趋势曲线绘制imagepilot实现多态指示灯控件配合open62541开源栈完成跨平台UA通信可直接编译运行并快速适配实际产线场景。 先从结论说起这个项目我前后折腾了将近两周踩了证书、时序、类型映射一堆坑之后才把整条链路跑通。现在这套基于QT和OPC-UA通信的西门子1200PLC上位机源码我已经在实际产线上稳定跑了三个月期间除了例行维护基本没掉过链子。打算把这套东西的完整设计思路、关键实现细节和调试经验一次性写清楚。如果你正准备做西门子PLC的上位机正在纠结选S7协议还是OPC-UA或者已经在用OPC-UA但被各种细节卡住这篇文章应该能帮你省下大量试错时间。内容会涵盖协议选型逻辑、西门子1200侧配置、QT工程搭建、核心通信代码、界面刷新策略以及一整套排坑经验尽量做到看完就能照着落地。1. 方案选型为什么是QT加OPC-UA而不是S7协议直连1.1 项目最初的定位与需求边界我接到这个需求时的场景是这样的现场有一条半自动装配线下位机是西门子S7-1200系列PLC需要做一个上位机监控程序负责实时显示设备状态、关键参数曲线、报警信息同时支持手动写入一些工艺参数。设备数量不多单台PLC点位大概一百多个但有一个硬性要求——这台上位机需要部署在国产化电脑上操作系统可能是麒麟或者统信UOS。这个要求直接排除了WinCC、LabVIEW这些传统方案也排除了基于Windows Only的S7通信库。综合评估下来QT加OPC-UA成了最稳的组合QT的跨平台能力不用多说C开发效率虽然不如C#但胜在UI渲染性能和部署灵活性OPC-UA则是西门子1200原生支持的通信协议不需要额外买授权也不依赖西门子自带的Simatic NET或S7通信DLL。1.2 S7协议直连的痛点做西门子上位机的人很多人第一反应是用S7协议直连毕竟网上开源的Snap7库用起来确实方便代码也简单。但我劝你先想清楚几个问题再做决定。Snap7确实能通过以太网直读PLC的DB块、M区、I/Q区响应速度快协议开销小开发门槛也不高。但它的局限非常明显首先是平台兼容性Snap7虽然有Windows和Linux版本但在国产化系统上编译经常遇到依赖库问题而且官方文档对ARM架构的支持比较含糊其次是安全性S7协议本身几乎没有安全机制明文传输一旦上位机被植入恶意程序PLC几乎等于裸奔最关键的是扩展性如果你的车间以后要加第二台PLC或者要接MES系统S7协议就不够看了每增加一个节点就要写一套连接逻辑。1.3 OPC-UA的核心优势OPC-UA的全称是OPC Unified Architecture统一架构。它和传统OPC-DA最大的区别在于不依赖COM/DCOM组件跨平台能力天然就强内置了信息安全和会话加密机制证书认证虽然麻烦但安全级别完全不在一个档次数据模型是面向对象的PLC里的DB块、结构化变量都能原样映射成服务器端的节点树层次清晰。对西门子1200来说从固件V4.0开始就原生内置了OPC-UA服务器你只需要在PLC侧启用并配置安全策略上位机就能以一个客户端身份接入。整个过程不需要在PLC上写任何额外程序这是S7协议做不到的。我选型时还有一层考量OPC-UA是国际标准IEC 62541意味着未来无论接MES、接云平台还是接其他品牌PLC这套上位机的通信层代码基本可以原样复用。做工业软件的人都知道通信层往往是整个项目里最伤筋动骨的部分能一次选对标准后面能省无数事。2. 整体架构设计从通信层到界面层的分层思路2.1 上位机软件的分层结构这套程序的代码结构我一开始就按分层思路来组织避免所有逻辑堆在一个类里后期改起来想哭。通信层OpcUaClientManager负责OPC-UA客户端的创建、连接、断开、订阅、读写操作对上层屏蔽协议细节。数据层DataModel定义PLC点位的数据结构维护变量映射关系处理数据类型转换和单位换算。业务层BusinessLogic报警判断、数据统计、工艺逻辑、联动控制等业务规则不直接接触通信接口。界面层MainWindow、Widgets负责数据显示、用户交互、曲线绘制、报警列表展示。每层之间有明确的接口约定通信层只向上层抛简单信号比如dataUpdated(QString tagName, QVariant value)、connectionStateChanged(bool connected)。上层只管消费数据不需要关心底层是OPC-UA还是MQTT还是Modbus将来如果换协议只要重写通信层实现就行。2.2 为什么选用QWidget而不是QML这个问题在QT社区里争论很多。QML做动画和炫酷界面确实方便但做工业上位机我更推荐QWidget。原因有几点第一工业场景的数据刷新非常频繁表格、曲线、仪表盘这类控件在QWidget里能用Model/View架构高效更新而QML的响应式绑定期数据量一大容易造成界面卡顿。第二QWidget的调试工具更成熟Qt Designer可视化编辑布局代码生成后可控性强。第三工控上位机的操作者一般是车间师傅界面以清晰直观为主QWidget的经典风格反而比QML的现代风更合适。我实测下来一套200个标签页的监控界面QWidget的帧率稳定在60FPSCPU占用不到15%而同样逻辑用QML实现CPU占用要到25%以上。当然这是个人经验仅供参考。2.3 通信线程与UI线程的职责划分这是整个程序设计的重中之重也是最容易犯错误的地方。OPC-UA的通信回调、订阅事件、读写操作都必须放在独立的通信线程中执行绝对不能直接在UI线程里同步调用读写。原因很简单OPC-UA的读写是网络IO操作单次往返可能几十到几百毫秒如果放在UI线程用户点一下按钮界面就无响应半秒钟体验极差。我的处理方式是通信线程跑一个QThread事件循环OPC-UA的client对象创建在这个线程里所有通信操作都通过信号槽投递到通信线程执行。具体来说UI层要读数据时不是直接调用通信层的读写函数而是emit一个信号通信线程收到信号后执行实际读写完成后再emit数据更新信号回UI线程。这里有一个QT的经典陷阱跨线程信号槽连接时一定要正确指定连接类型。默认的AutoConnection在线程间会自动切换为QueuedConnection这是安全的。但如果你在通信线程中直接调用UI控件的更新函数或者反过来在UI线程中直接操作通信对象就会导致崩溃或无法预料的竞态问题。3. 西门子1200PLC侧的OPC-UA服务器配置3.1 启用PLC的OPC-UA服务器功能S7-1200启用OPC-UA服务器的操作本身并不复杂但很多细节藏得比较深第一次配置容易漏。我以博途TIA Portal V16以上版本为例说明完整的配置流程。第一步在设备视图中选中CPU进入“属性-常规-OPC-UA设置”勾选“激活OPC-UA服务器”。这里要注意不同固件版本支持的安全策略数量不同V4.4及以上固件支持Basic256Sha256、Basic256、Basic128Rsa15等策略V4.0以下固件可能只支持Basic128Rsa15。第二步配置端口号。默认端口是4840一般不需要改。但如果你现场有多台PLC或服务器占用了这个端口需要改成其他端口同时确保上位机能通过网络访问到这个端口。第三步安全策略选择。最省事的做法是选择“无安全策略”这样上位机不需要证书认证但这不是生产环境的推荐做法。生产环境下我建议至少启用Basic256Sha256配置证书认证。3.2 证书管理与安全策略设置如果你只是在自己电脑上调试选“无安全策略”能省很多事。但一旦部署到生产环境我强烈建议开启证书认证。流程是这样的在PLC侧生成一个服务器证书然后把这个证书导出在上位机的OPC-UA客户端中导入并信任。同样上位机客户端也要生成自己的客户端证书导入到PLC的受信任证书列表中。听起来很绕实际操作中我走了不少弯路。最典型的坑就是第一次连接时客户端会收到服务器的证书如果客户端不信任这个证书握手直接失败错误信息提示是BadCertificateUntrusted。而博途界面上证书管理的位置藏在“OPC-UA设置-安全”标签页里不仔细找很容易遗漏。调试阶段的小窍门可以先把PLC的安全策略设为“无”确保通信链路跑通再去启用证书认证。这样能把“网络不通”和“证书不信任”两类问题分开排查。3.3 DB块与变量的节点地址规划OPC-UA通信的本质是访问服务器的节点树西门子1200将PLC中的变量映射为带命名空间的节点ID。节点ID的格式一般是ns3;sDB名称.变量名例如ns3;sDB_Data.CurrentTemp。但这个命名空间索引不是固定的它取决于PLC的地址空间。在博途里你可以在“OPC-UA设置”页面查看到当前PLC的节点命名空间索引常见的是ns3对应程序块中的变量有些固件会用到ns4或更高。我建议的做法是在PLC侧把所有需要上位机访问的变量集中放到一两个DB块里并给DB块起一个容易识别的名字。这样一方面节点地址好记另一方面西门子1200的OPC-UA服务器在启动时会把DB块的结构信息上抛客户端能直接浏览到完整的数据类型省去手动构造节点ID的麻烦。4. 基于QT的OPC-UA客户端实现细节4.1 开发环境与依赖库准备QT版本我选的是5.15.2这个版本稳定对OPC-UA模块的支持已经比较成熟。从QT5.13开始QT就引入了QtOpcUa模块GPL/商业双许可底层后端可以选open62541或uacpp即UAC。这里有个关键选型你的QT安装包默认自带QtOpcUa模块但后端需要单独编译或安装。open62541是纯C实现的轻量级库编译简单跨平台友好我用的就是它。uacpp功能更全但编译麻烦依赖OpenSSL等外部库。在Windows上如果你习惯用MSVC编译套件需要自己编译open62541并配置到项目里。我实际推荐用MinGW套件配合预编译的open62541库省去很多环境折腾。编译时记得加-DUA_ENABLE_ENCRYPTIONON否则不支持安全策略。CMake配置大致是find_package(Qt5 COMPONENTS Widgets OpcUa REQUIRED) target_link_libraries(yourTarget Qt5::Widgets Qt5::OpcUa)如果你用的是qmake则在.pro文件里加QT opcua4.2 客户端连接与断线重连机制OPC-UA客户端的连接流程比TCP复杂涉及通道建立、会话创建、安全握手等多个环节。我用QOpcUaClient的异步接口实现了一个可复用的客户端管理类。核心思路是// 创建客户端对象注意必须在通信线程中创建 m_client new QOpcUaClient(QOpcUa::open62541, this); // 设置连接地址格式如 opc.tcp://192.168.0.10:4840 m_client-connectToEndpoint(endpointUrl);连接结果通过信号返回分别是connected()和connectError(QOpcUaClient::ClientError error)。还有一个重要的信号是stateChanged(QOpcUaClient::ClientState state)这个信号会在连接状态切换时触发比如从Connected变成Disconnected或者从Connecting变成Connected。我的断线重连逻辑就建立在这个状态信号上如果检测到Disconnected且不是主动断开就启动一个QTimer每5秒尝试重连一次直到恢复。重连时要注意一个问题连接断开后之前创建的订阅节点、读取项全部失效必须重新创建。所以我在重连成功后会调用一个initSubscriptions()函数把所有的点位订阅重新注册一遍。4.3 数据读取的三种方式与选型OPC-UA提供了读取数据的三种方式我在实际项目中都用到过这里做个对比直接读取Read客户端主动发送读取请求服务器返回结果。适合低频读取比如按钮点击后读取一个参数值。缺点是每次请求都有网络往返高频读取浪费带宽有阻塞风险。订阅Subscribe客户端创建一个订阅Subscription把需要监视的节点加入监控项服务器定期推送数据变化。这是做实时监控的首选方案西门子1200的OPC-UA服务器支持最低100ms的发布间隔足够平滑地绘制曲线。历史读取HistoryRead从服务器保存的历史数据中查询。西门子1200默认不启用历史存储需要额外配置实际用到的情况不多。我的程序里实时变量全部走订阅按钮触发的参数读写走直接读取。订阅的发布间隔PublishingInterval设置为200ms数据变化阈值Deadband设为0.1%的绝对值量程这样既能保证实时性又不会因为噪声数据导致UI频繁刷新。4.4 订阅机制的核心代码实现创建订阅的代码大致如下// 创建订阅 QOpcUaSubscription *subscription m_client-createSubscription(200); // 200ms发布间隔 connect(subscription, QOpcUaSubscription::valueChanged, this, ClientManager::onValueChanged); // 添加监控节点 QOpcUaMonitoringItem *item subscription-addMonitoringItem(nodeId); item-setDataType(QOpcUa::Types::Double); item-setPublishingInterval(200); item-setSamplingInterval(100); item-setDeadband(1.0); // 绝对值死区单位是EU工程单位订阅的回调信号是valueChanged(QOpcUaMonitoringItem* item, QOpcUaReadResult value)在回调里可以拿到节点的值和状态码。如果状态码不是Good说明数据无效可能是变量被PLC侧删除了或者类型变了要注意处理。这里有个特别容易踩的坑QOpcUaMonitoringItem在创建后连接结果同样是通过信号返回的你必须在stateChanged信号里确认它成功进入了Active状态才能认为订阅真正生效。如果没等成功就读取数据返回的会是错误码。4.5 数据类型映射与单位处理PLC侧的数据类型和QT原生类型之间并不是一一对应的这是新手特别容易忽略的地方。SIEMENS Bool在OPC-UA客户端得到的是QOpcUaReadResult中的bool值没问题SIEMENS Real对应doubleSIEMENS Int对应qint16SIEMENS DInt对应qint32SIEMENS LReal对应double。但有些类型需要特别注意SIEMENS String映射为QString但OPC-UA中有两种编码ByteString和String如果PLC侧用STRING(255)类型默认是ByteString编码需要做字节转字符处理。SIEMENS Date/Time映射为QDateTime但PLC侧的时间精度是秒实际刷新存在延迟。生产环境中很多变量是带单位的比如温度、压力、速度PLC侧不会自动把单位换算成工程值。你需要在数据层维护一张映射表记录每个点位的量程范围、偏移和单位。我推荐建一个结构体来定义点位struct PlcTagInfo { QString nodeId; // OPC-UA节点ID QString description; // 描述 double scaleMin; // 量程下限 double scaleMax; // 量程上限 double offset; // 偏移量 double gain; // 增益系数 QString unit; // 单位 QVariant value; // 当前值 quint32 quality; // 数据质量 };在UI上显示时用rawValue * gain offset换算成工程值。这样即使PLC侧改了量程上位机只需调整映射表即可不用改PLC程序。5. 界面开发与业务逻辑集成5.1 主界面布局与控件规划整个主界面我做成三栏布局左侧是设备状态面板中间是实时监控区域包含数据表格和实时曲线右侧是报警信息列表和控制按钮。顶部是工具栏和连接状态指示灯。连接状态指示灯非常关键我用一个自定义绘制的圆形控件绿色表示连接正常黄色表示正在重连红色表示连接失败同时附带最后一次断线原因的文字描述。现场的工人看到灯变黄就知道上位机在自动重连不会误以为死机。数据表格选用了QTableView配合自定义的QAbstractTableModel实现。这个Model直接持有PLC点位的数据缓存界面更新时只刷新可见区域性能比直接往QTableWidget里塞数据高一个量级。实时曲线是用QCustomPlot做的轻量且容易上手。曲线刷新频率和订阅发布间隔保持一致数据变化时通过replot()重绘。5.2 数据驱动的UI刷新策略工业上位机UI最忌讳的写法是每个定时器周期都把几百个控件全量刷新一遍。那种做法连最简单的状态指示灯快了都闪更别说表格和曲线了。我的做法是建立信号驱动的更新机制。一个点位值变化时通信层发出dataUpdated(QString tagName, QVariant value)信号UI层收到后只更新对应控件。这样高频点位的刷新频率可以到几十Hz但低频点位不会拖累整体性能。为了减少信号连接的数量我并没有让每种控件都直接连到通信层的信号上而是让DataModel持有一个共享的数据缓存用QHashQString, QVariant维护最新值。UI控件只订阅它关心的几个标签数据更新时从缓存里取最新值。这样还有一个好处重连恢复后数据缓存自动保留最后值不会出现重连期间UI变空白的情况。5.3 参数写入与操作权限控制PLC参数的写入比读取要复杂因为涉及安全性和操作确认。我在UI上把写操作设计成两步确认模式弹出对话框显示当前值和目标值用户须点“确认写入”后才真正执行OPC-UA写入。写操作的权限控制我没有做得太复杂只是根据登录用户的角色来区分。普通操作员只能写工艺流程参数工程师可以写所有参数管理员还能修改系统配置。角色信息存在配置文件里写操作前会在业务层校验权限码。写入时使用QOpcUaClient::writeNodeValue和writeNodeAttributes两个API。writeNodeValue用于写值writeNodeAttributes可以写节点的其他属性实际中用得少。写入完成后要检查返回值如果返回QOpcUaClient::Good才表示成功。有一点经验要分享OPC-UA写入的类型必须和节点实际类型严格匹配。如果你写入一个double值到Real类型的节点客户端会返回类型不兼容错误。西门子1200的S7-1200中一个DB块里如果变量定义是Real你写double虽然都是浮点但也可能会被拒绝必须按标准类型映射去对应。5.4 报警系统的设计思路报警功能的实现思路不复杂但很容易做得粗糙。我的报警系统分两层第一层是瞬时报警比如温度超过上限立即在报警列表中插入一条记录同时在界面上弹出非模态的报警横幅。第二层是历史报警保存到本地的SQLite数据库里方便之后查询。报警逻辑写在业务层通过订阅的回调实时判断if (tagInfo.value.toDouble() tagInfo.highLimit) { emit alarmTriggered(tagInfo, AlarmHigh); }为了减少误报我加了持续确认机制连续3个采样周期都超限才判定为报警并且记录第一次超限的时间。现场振动等瞬时干扰导致的尖峰就用这个办法滤掉了。报警记录加上了确认和复位按钮确认按钮表示操作员已经看到报警复位按钮表示现场故障已解决。报警状态在界面上用醒目的红黄双色区分红色闪烁表示未确认黄色常亮表示已确认未复位。6. 实际部署中的问题与调试技巧6.1 网络环境与防火墙设置OPC-UA默认使用TCP端口4840但如果你的现场网络划分了VLAN或者有硬件防火墙连接失败的第一反应应该就是查端口通不通。我用一个很土但很有效的命令检查ping 192.168.0.10 telnet 192.168.0.10 4840如果telnet能连上端口但OPC-UA还是握手失败那大概率是安全策略或证书问题。如果telnet超时那就去查交换机和防火墙配置。还有一点西门子1200的服务器地址我建议固定为静态IP不要用DHCP。因为OPC-UA客户端连接靠的是IP加端口动态IP重连时如果变了就要改上位机配置这对现场调试和远程运维都非常麻烦。6.2 证书问题的定位与解决证书问题在上位机调试中出现的概率非常高我把典型问题整理成一张速查表方便对照排查错误状态码含义排查方向BadCertificateUntrusted服务器不信任客户端证书将客户端证书导入PLC受信任列表BadCertificateTimeInvalid证书时间无效检查PLC和上位机系统时间是否一致BadCertificateHostNameInvalid证书主机名不匹配配置的Endpoint地址与证书内的主机名不一致BadSecurityModeRejected安全模式被拒绝确认PLC和客户端的安全策略一致BadSecurityPolicyRejected安全策略被拒绝确认PLC启用的安全策略一致最简单的一次排查还没加安全策略时连接正常加了证书认证后连不上先用状态码对号入座。如果是时间不同步同步一下时间就通。6.3 性能调优与资源占用生产环境跑了三个月后有一个性能问题值得一提长时间运行后内存占用会缓慢增长最终稳定在一个较高的水平。排查后发现是OPC-UA订阅过程中QT的QOpcUaBackend内部会对数据变更做缓冲队列如果UI消费速度跟不上网络数据速度队列就会积压。解决办法有两步第一步调大监控项的采样间隔和发布间隔让数据频率降到UI能处理的范围第二步在通信层回调中增加逻辑如果数据缓存里的值和前一次相同就不发dataUpdated信号减少UI刷新频率。另外要做好定时清理历史报警SQLite表按时间定期归档删除防止数据无限膨胀。6.4 调试工具与日志系统上位机上线后日志系统是救命稻草。我写了一个轻量级日志模块支持分级输出Debug/Info/Warning/Error同时输出到控制台和按天滚动的文件。日志里记录什么内容连接状态变化、读写操作结果、错误详情、数据质量码变化这些都要记录下来。现场出现问题时先看日志是第一步。调试阶段推荐用UaExpert这个免费的OPC-UA客户端工具它能浏览服务器端节点树、测试读写、查看证书信息是排查“到底是上位机问题还是PLC服务器问题”的利器。我一般流程是先用UaExpert能连上PLC再怀疑自己写的上位机代码如果UaExpert也连不上就去查PLC侧配置和网络。7. 项目源码的核心模块拆解7.1 通信层代码结构通信层是整个上位机的核心我把几个关键类的职责梳理如下OpcUaClientManager管理QOpcUaClient生命周期、连接、重连、订阅管理对外提供信号和槽函数。NodeManager维护节点ID与PLC变量的映射关系提供节点地址解析、数据类型转换。DataCache线程安全的共享数据缓存保存所有点位的最新值。WriteManager处理写入操作的队列和权限校验避免并发写入冲突。通信线程的启动和管理我继承了一个QThread子类把QOpcUaClient的创建和事件循环都放在该线程内。这里有一个细节QOpcUaClient的构造函数必须在通信线程中执行否则在Qt的open62541后端里可能出现跨线程访问不稳定。7.2 生产环境下的稳定性措施上位机程序强杀、断电重启、网络闪断这些情况在工业现场都经常发生。针对这些场景我加了几个稳定性措施第一看门狗机制。程序内部有一个看门狗定时器如果主界面事件循环卡死超过10秒程序自动重启。这个听起来有点粗暴但在无人工干预的夜班场景里非常管用。第二配置文件自动备份。连接参数、点位映射表等配置文件每次启动时自动复制一份带时间戳的备份如果配置文件损坏程序能回滚到上一个可用版本。第三报警自动恢复。程序启动时自动从SQLite中恢复未解决的报警记录避免重启后报警信息丢失。第四PLC侧参数变更的自动同步。如果PLC程序修改导致节点ID变化上位机连接后通过浏览服务器节点树来校验映射表发现不一致就在日志中警告但不会直接退出。7.3 链接库部署与跨平台打包项目最终部署到几台不同操作系统的主机上有Windows 10、麒麟V10、UOS 20。QT跨平台开发最大的坑就是“本地编译能跑换台机器就缺DLL”。我的经验是在Windows上用windeployqt工具把Qt运行库和插件自动拷贝到发布目录同时手动添加open62541.dll和SSL依赖库。在Linux上用linuxdeployqt工具打包AppImage格式或者直接做deb包。国产系统上偶尔会遇到缺少libatomic等基础库的情况提前用ldd检查依赖在部署文档里写清楚需要预装哪些包。其实如果你的部署范围可控比如就两三台机更省事的方案是把编译环境直接装到目标机器上用动态库链接省去打包时的一堆破事。8. 复盘与建议这套方案适合什么场景用QT加OPC-UA做西门子1200的上位机这套组合并不是唯一选择但它在跨平台、标准化、扩展性这条路上确实是最舒服的。如果你只需要自己开发一个单机版的上位机跑在Windows上那用C# WinForm加Snap7库可能更快捷开发效率更高资料也更多。但如果你面对的是设备要接入MES、系统要部署到国产操作系统、车间以后可能要增加设备那OPC-UA这套方案就是提前布局。具体到选型上有一点很明确西门子1200自带OPC-UA服务器不需要额外授权这是S7-1500同规格下都不一定具备的优势。既然PLC侧已经白送了这么好的功能上位机这边不做OPC-UA通信而用S7协议直连其实有点浪费。另一个建议是如果团队里C#经验更丰富可以直接采用C#加OPC-UA基金会提供的.Net Standard库阿帕奇2.0开源的OPCUA.NETStandard项目成熟度也很高。QT和C#选哪一个主要看团队技术栈和部署环境。代码层面通信架构和状态机设计是通用的换语言只是翻译一下API调用。最后再说一个从现场运维角度总结的小技巧部署完成后一定要同时把UaExpert和Wireshark装到维护电脑上。Wireshark抓包OPC-UA可能是二进制格式需要加解密不太好看但至少能确认TCP握手有没有通。真到了排查问题时多一个抓包工具就是多一条活路。到现在为止这套源码已经在产线上连续运行三个月故障基本都集中在网络抖动引起的重连而重连机制每次都自动恢复了没有一次需要人工干预。这个结果还是让人满意的。对于正在做类似项目的人我只能说通信链路的坑早踩早好代码架构设计多花两天心思后面能省两个月时间。本文还有配套的精品资源点击获取