跳到主要内容

browse

browse(node_id, filter = NodeClass.Unspecified) — 列出指定节点的直接子节点 (一层).

前置阅读 / 配套

签名

def browse(self,
node_id: str,
filter: NodeClass = NodeClass.Unspecified) -> List[Reference]: ...

def browse_many(self,
node_ids: List[str],
filter: NodeClass = NodeClass.Unspecified) -> List[List[Reference]]: ...

Reference 字段

字段类型说明
node_idstr子节点 NodeId
browse_namestr浏览名
display_namestr显示名
node_classNodeClass子节点类别

Reference.to_node(session) 转为可操作的 OpcUaNode.

例子

from opcua import NodeClass

# 列出 Boiler1 下所有子节点
children = ua.browse("ns=2;s=Boiler1")
for c in children:
print(f" {c.node_class.name} {c.browse_name} -> {c.node_id}")

# 只看 Variable 类型
vars_ = ua.browse("ns=2;s=Boiler1", filter=NodeClass.Variable)

# 只看 Method
methods = ua.browse("ns=2;s=Calculator", filter=NodeClass.Method)

批量浏览 (browse_many)

如果同时要浏览多个节点 (例如 GUI 初次展开树), 用 browse_many 一次 RPC:

roots = ["i=85" /* Objects */, "i=86" /* Types */]
results = ua.browse_many(roots)
for nid, refs in zip(roots, results):
print(f"{nid}:")
for c in refs:
print(f" {c.browse_name}")

如果某个节点浏览失败 (NodeId 错), 对应槽位返回空列表, 不抛异常.

NodeClass filter

包含
Unspecified (0)全部
Object (1)仅 Object
Variable (2)仅 Variable
Method (4)仅 Method
Object | Variable (按位或)组合

异常

OpcUaException(BadNodeIdUnknown) / OpcUaException(BadCommunicationError) 等. transport 失败抛, 单个子节点失败不抛.

大节点的分页 (ContinuationPoint)

如果一个节点有 1000+ 个子节点, 单次 browse 服务端可能截断. 此时 browse 只返回第一页.

要看全部, 用 browse_with_paging + browse_next:

page = ua.browse_with_paging("ns=2;s=BigFolder")
all_refs = list(page.references)
while page.continuation_point is not None:
page = ua.browse_next(page.continuation_point)
all_refs.extend(page.references)

性能

  • 单次 browse: ~5-15 ms (网络往返 + 服务端遍历)
  • browse_many 批量: 总耗时 ~ 单次 (省 N-1 次往返)
  • 1000+ 子节点会分页, 加 browse_next 处理

browse_filtered — 方向 + 引用类型过滤

browse_filteredbrowse 的基础上加 BrowseDirection + reference_type_id + include_subtypes + result_mask 过滤 (Part 4 §5.8.2.2).

def browse_filtered(self,
nid: str,
node_class_filter: NodeClass = NodeClass.Unspecified,
direction: BrowseDirection = BrowseDirection.FORWARD,
reference_type_id: str = None,
include_subtypes: bool = True,
result_mask: int = 0x3F) -> List[Reference]: ...

相关结构:

class BrowseDirection(IntEnum):
FORWARD = 0 # 仅正向 (出引用), 父→子
INVERSE = 1 # 仅反向 (入引用), 子→父
BOTH = 2 # 正反向都返回

示例

from opcua import BrowseDirection

# 1) 正向 + 仅 HierarchicalReferences (i=33)
children = ua.browse_filtered("ns=2;s=Boiler1",
direction=BrowseDirection.FORWARD,
reference_type_id="i=33",
include_subtypes=True)

# 2) 反向找父
parents = ua.browse_filtered("ns=2;s=Tank.Level",
direction=BrowseDirection.INVERSE)
for p in parents:
print(f"父: {p.browse_name}")

# 3) 双向
all_refs = ua.browse_filtered("ns=2;s=Robot.Joint1", direction=BrowseDirection.BOTH)

实现说明

  • Stack 提供 DarraUa_Session_BrowseWithFilter 时直调原生
  • 否则 fallback 到 browse + 客户端按 NodeClass 过滤; reference_type_id / direction 在 fallback 模式下无法精确生效, 打 Warning

browse_all — 自动续翻

def browse_all(self, node_id: str,
filter: NodeClass = NodeClass.Unspecified,
max_pages: int = 32) -> List[Reference]: ...

自动反复调 browse_next 直到 ContinuationPoint 为空:

all_refs = ua.browse_all("ns=2;s=BigFolder")
print(f"共 {len(all_refs)} 个子节点")

下一步