#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 节点访问诊断脚本 帮助诊断OPC UA节点访问问题 """ import sys import time # 添加项目路径 sys.path.insert(0, r"d:\f-work\three_control_system\Feeding1129\opc") from opcua_client_test import OPCUAClientTest def diagnose_node_access(): """诊断节点访问问题""" print("=" * 60) print("OPC UA 节点访问诊断") print("=" * 60) # 创建客户端 client = OPCUAClientTest() try: # 连接到服务器 print("\n[1] 连接到OPC UA服务器...") if not client.connect(): print("连接失败!") return print("连接成功!") # 获取对象节点 objects = client.client.get_objects_node() print(f"\n对象节点: {objects}") print(f"对象节点ID: {objects.nodeid}") # 浏览所有子节点 print("\n[2] 浏览对象节点下的所有子节点...") try: children = objects.get_children() print(f"子节点数量: {len(children)}") for i, child in enumerate(children): try: browse_name = child.get_browse_name() node_id = child.nodeid print(f" {i+1}. {browse_name} -> {node_id}") except Exception as e: print(f" {i+1}. (获取名称失败: {e})") except Exception as e: print(f"浏览子节点失败: {e}") # 尝试不同的路径格式 print("\n[3] 尝试不同的路径格式访问节点...") path_formats = [ # 格式1: 使用命名空间前缀 "2:upper/2:upper_weight", "2:lower/2:lower_weight", # 格式2: 原始字符串(避免转义问题) r"2:upper/2:upper_weight", r"2:lower/2:lower_weight", # 格式3: 使用列表格式 ["2:upper", "2:upper_weight"], ["2:lower", "2:lower_weight"], # 格式4: 不带命名空间前缀 "upper/upper_weight", "lower/lower_weight", ["upper", "upper_weight"], ["lower", "lower_weight"], ] for path in path_formats: try: if isinstance(path, list): node = objects.get_child(path) else: node = objects.get_child(path) browse_name = node.get_browse_name() value = node.get_value() print(f" ✓ 成功: {path}") print(f" 节点: {node}") print(f" 名称: {browse_name}") print(f" 值: {value}") print() # 找到一个有效的就继续尝试其他格式 break except Exception as e: print(f" ✗ 失败: {path}") print(f" 错误: {e}") print() # 尝试方法1:先获取设备对象,再获取变量 print("\n[4] 方法1: 先获取设备对象,再获取变量...") try: upper_device = objects.get_child("2:upper") print(f" 上料斗设备: {upper_device}") upper_weight = upper_device.get_child("2:upper_weight") value = upper_weight.get_value() print(f" ✓ 成功获取上料斗重量: {value}") except Exception as e: print(f" ✗ 失败: {e}") # 尝试方法2:直接使用完整路径 print("\n[5] 方法2: 直接使用完整路径...") try: # 注意:这里使用原始字符串避免转义问题 upper_weight = objects.get_child(r"2:upper/2:upper_weight") value = upper_weight.get_value() print(f" ✓ 成功获取上料斗重量: {value}") except Exception as e: print(f" ✗ 失败: {e}") # 尝试方法3:使用get_children遍历 print("\n[6] 方法3: 使用get_children遍历查找...") try: for child in objects.get_children(): try: browse_name = str(child.get_browse_name()) if "upper" in browse_name.lower(): print(f" 发现上料斗相关节点: {browse_name} -> {child.nodeid}") # 尝试获取该节点的子节点 for sub_child in child.get_children(): try: sub_browse_name = str(sub_child.get_browse_name()) if "weight" in sub_browse_name.lower(): value = sub_child.get_value() print(f" └─ {sub_browse_name}: {value}") except Exception as e: print(f" └─ 获取{sub_browse_name}失败: {e}") except Exception as e: print(f" 处理节点失败: {e}") except Exception as e: print(f" ✗ 遍历失败: {e}") # 尝试写入操作 print("\n[7] 尝试写入操作...") try: # 找到有效的节点路径 upper_device = objects.get_child("2:upper") upper_weight = upper_device.get_child("2:upper_weight") # 写入测试值 test_value = 123.45 upper_weight.set_value(test_value) print(f" ✓ 成功写入: {test_value}") # 读取验证 read_value = upper_weight.get_value() print(f" ✓ 读取验证: {read_value}") except Exception as e: print(f" ✗ 写入失败: {e}") import traceback traceback.print_exc() except Exception as e: print(f"\n诊断过程出错: {e}") import traceback traceback.print_exc() finally: try: client.disconnect() print("\n[8] 已断开连接") except: pass print("\n" + "=" * 60) print("诊断完成") print("=" * 60) if __name__ == "__main__": diagnose_node_access()