You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node-RED中Python编写的OPC Client运行1小时后报错求助

OPC客户端运行1小时后报错修复方案

问题背景

用Python编写的OPC UA客户端在Node-RED中运行,负责将传感器数据上传至Thingsboard,运行约1小时后出现连接相关报错。

原代码

from opcua import Client
import paho.mqtt.client as mqtt
import time
import json

url = "opc.tcp://D201002809747:4840"
client = Client(url)
client.connect()
print ("已连接OPC服务器")

iot_hub = "iothub.toyota.co.id"
port = 1883  # MQTT默认端口,原代码留空会导致连接失败
username = "MdduLiSzC787aY8DrYNf"
password = ""
topic = "v1/devices/me/telemetry"

iot_hub_client = mqtt.Client()
iot_hub_client.username_pw_set(username, password)
iot_hub_client.connect(iot_hub, port)
print ("已连接IoT Hub")

data = dict()
while True:
    el = client.get_node("ns=2;s=Device1.DATA.MOTOR_CV3_ALONGATION")
    elongation = el.get_value()
    print (elongation)

    data['Elongation'] = int(elongation)
    data_out = json.dumps(data)
    iot_hub_client.publish(topic, data_out, 0)
    
    time.sleep(2)

注:原代码存在两处基础问题:while True循环内代码未缩进(语法错误)、MQTT端口留空,上述代码已先行修正。

错误信息(翻译后)

退出代码:1
回溯(最近调用最后):
  文件 "C:\Users\admin\coba.py", 第25行, in <module>
    elongation = el.get_value()
                ^^^^^^^^^^^^^^
  文件 "C:\Users\admin\AppData\Roaming\Python\Python311\site-packages\opcua\common\node.py", 第155行, in get_value
    result = self.get_data_value()
             ^^^^^^^^^^^^^^^^^^^^^
  文件 "C:\Users\admin\AppData\Roaming\Python\Python311\site-packages\opcua\common\node.py", 第164行, in get_data_value
    return self.get_attribute(ua.AttributeIds.Value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  文件 "C:\Users\admin\AppData\Roaming\Python\Python311\site-packages\opcua\common\node.py", 第275行, in get_attribute
    result = self.server.read(params)
             ^^^^^^^^^^^^^^^^^^^^^^^^
  文件 "C:\Users\admin\AppData\Roaming\Python\Python311\site-packages\opcua\client\ua_client.py", 第347行, in read
    data = self._uasocket.send_request(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  文件...

问题原因分析

  1. OPC UA连接无重连机制:长时间运行中,OPC服务器可能因超时、网络波动主动断开连接,原代码未处理连接丢失情况,一旦断开就会抛出请求失败错误。
  2. MQTT连接未做保活:MQTT连接同样可能因网络问题断开,原代码无重连逻辑,会导致数据无法上传。
  3. 缺少异常捕获:运行过程中出现的网络异常、节点读取异常未被捕获,直接导致程序崩溃。

修复后的代码

from opcua import Client, ua
import paho.mqtt.client as mqtt
import time
import json

# OPC UA配置
OPC_URL = "opc.tcp://D201002809747:4840"
NODE_ID = "ns=2;s=Device1.DATA.MOTOR_CV3_ALONGATION"

# MQTT配置
IOT_HUB = "iothub.toyota.co.id"
MQTT_PORT = 1883
USERNAME = "MdduLiSzC787aY8DrYNf"
PASSWORD = ""
TOPIC = "v1/devices/me/telemetry"

def connect_opc():
    """创建并连接OPC客户端"""
    try:
        opc_client = Client(OPC_URL)
        opc_client.connect()
        print("已重新连接OPC服务器")
        return opc_client
    except Exception as e:
        print(f"OPC连接失败: {str(e)}")
        return None

def connect_mqtt():
    """创建并连接MQTT客户端"""
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("已重新连接IoT Hub")
        else:
            print(f"MQTT连接失败,错误码: {rc}")
    
    mqtt_client = mqtt.Client()
    mqtt_client.username_pw_set(USERNAME, PASSWORD)
    mqtt_client.on_connect = on_connect
    # 开启自动重连,设置重连延迟范围
    mqtt_client.reconnect_delay_set(min_delay=1, max_delay=60)
    try:
        mqtt_client.connect(IOT_HUB, MQTT_PORT, keepalive=60)
        mqtt_client.loop_start()
        return mqtt_client
    except Exception as e:
        print(f"MQTT连接初始化失败: {str(e)}")
        return None

# 初始化连接
opc_client = connect_opc()
mqtt_client = connect_mqtt()

data = dict()
while True:
    # 检查并重建OPC连接
    if not opc_client or not opc_client.is_connected():
        opc_client = connect_opc()
        time.sleep(5)
        continue
    
    # 检查并重建MQTT连接
    if not mqtt_client or not mqtt_client.is_connected():
        mqtt_client = connect_mqtt()
        time.sleep(5)
        continue
    
    try:
        # 读取OPC节点值
        el = opc_client.get_node(NODE_ID)
        elongation = el.get_value()
        print(f"读取到伸长值: {elongation}")
        
        # 上传数据到Thingsboard
        data['Elongation'] = int(elongation)
        data_out = json.dumps(data)
        mqtt_client.publish(TOPIC, data_out, qos=0)
        
    except ua.UaError as e:
        print(f"OPC数据读取错误: {str(e)}")
        opc_client = None  # 标记连接失效,触发下一次重连
    except Exception as e:
        print(f"其他运行错误: {str(e)}")
    
    time.sleep(2)

关键改进点

  • OPC连接重连逻辑:每次循环检查连接状态,断开时自动重建。
  • MQTT自动重连:开启MQTT客户端的自动重连机制,设置保活时间,避免连接丢失。
  • 异常捕获处理:捕获OPC UA专属错误和通用异常,程序不会因单次错误直接崩溃,而是尝试恢复。
  • 代码结构优化:将连接逻辑封装成函数,提升可读性和维护性。

内容的提问来源于stack exchange,提问作者Hendrianto29

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:25:33