diff --git a/opc/__init__.py b/opc/__init__.py new file mode 100644 index 0000000..877f241 --- /dev/null +++ b/opc/__init__.py @@ -0,0 +1,4 @@ +"""OPC包""" +from .client import OPCClient + +__all__ = ['OPCClient'] \ No newline at end of file diff --git a/opc/client.py b/opc/client.py new file mode 100644 index 0000000..3c25b79 --- /dev/null +++ b/opc/client.py @@ -0,0 +1,97 @@ +import threading +import time +from opcua import Client, ua +from opcua.ua.uaerrors import UaError +import json + + +class OPCClient: + def __init__(self, url='opc.tcp://127.0.0.1:4840'): + self.url = url + self.client = None + self.is_connected = False + self.reconnect_interval = 5 # 重连间隔(秒) + self.is_running = False + self.namespace_idx = None + self.data_node = None + + def connect(self): + """连接到OPC UA服务端""" + try: + if self.client: + self.client.disconnect() + + self.client = Client(self.url) + self.client.set_security_string("None") + self.client.connect() + + # 获取命名空间索引 + self.namespace_idx = self.client.get_namespace_index("urn:python-opcua") + + # 获取数据节点 + self.data_node = self.client.get_node(f"ns={self.namespace_idx};i=2001") # 默认数据节点 + + self.is_connected = True + print(f"已连接到 OPC UA 服务端 {self.url}") + return True + except UaError as e: + print(f"OPC UA 连接错误: {e}") + self.is_connected = False + return False + except Exception as e: + print(f"连接到 OPC UA 服务端失败: {e}") + self.is_connected = False + return False + + def start(self): + """启动客户端并维持连接""" + self.is_running = True + reconnect_thread = threading.Thread(target=self._reconnect_worker, daemon=True) + reconnect_thread.start() + + def _reconnect_worker(self): + """重连工作线程""" + while self.is_running: + if not self.is_connected: + print(f"尝试重新连接到 {self.url}...") + self.connect() + time.sleep(self.reconnect_interval) + + def send_data(self, data): + """通过OPC UA发送数据到服务端""" + if not self.is_connected or not self.client: + print("OPC UA 客户端未连接到服务端") + return False + + try: + # 将数据转换为JSON字符串 + json_data = json.dumps(data, ensure_ascii=False) + + # 写入数据到OPC UA节点 + if self.data_node: + variant = ua.Variant(json_data, ua.VariantType.String) + self.data_node.set_value(variant) + print(f"已通过 OPC UA 发送数据: {json_data}") + return True + else: + print("数据节点未初始化") + return False + except UaError as e: + print(f"OPC UA 发送数据时出错: {e}") + self.is_connected = False + return False + except Exception as e: + print(f"发送数据时出错: {e}") + self.is_connected = False + return False + + def stop(self): + """停止客户端""" + self.is_running = False + self.is_connected = False + if self.client: + try: + self.client.disconnect() + except Exception as e: + print(f"断开 OPC UA 客户端时出错: {e}") + print("OPC UA 客户端已停止") \ No newline at end of file