订阅自恢复
概述
Session 重连后, 服务端 Subscription 可能仍存活也可能已被清理。SDK 两步走:
- transfer_subscriptions — 把旧 SubscriptionId 转给新 Session
- Recreate — 转移失败时, 用本地缓存的 MonitoredItemSpec 重建 Sub + 全部 MI (含 DataChangeFilter / EventFilter / Triggering)
业务侧无需手动处理。
API
| 方法 / 事件 | 类别 | 读写 | 说明 |
|---|---|---|---|
| ua.transfer_subscriptions(old_sub_ids, send_initial_values) | 方法 | 写 | 转移订阅 |
| ua.events.on('subscription_lost', ...) | 事件 | 读 | 订阅丢失 |
| ua.events.on('subscription_restored', ...) | 事件 | 读 | 订阅恢复 |
代码示例
from opcua import (
DarraOpcUa, AttributeId, MonitoringMode,
DataChangeFilter, DeadbandType
)
with DarraOpcUa("opc.tcp://localhost:4840") as ua:
ua.connect()
@ua.events.on('subscription_lost')
def on_lost(args):
print(f"订阅丢失: sub_id={args.subscription_id}")
@ua.events.on('subscription_restored')
def on_restored(args):
print(f"订阅已恢复: {args.source}")
# 创建 sub + MI, 全程不变
sub = ua.create_subscription(500)
mi = sub.add("ns=2;s=Temp", AttributeId.VALUE, 200,
MonitoringMode.REPORTING, 10, True,
DataChangeFilter(deadband_type=DeadbandType.ABSOLUTE, deadband_value=0.5))
@sub.on_data_changed
def on_dc(args):
print(f"{args.value.value} @ {args.value.source_timestamp}")
# 拔网线 30 秒, 看日志:
# reconnecting → reconnected → subscription_restored
# 数据自动续上, filter 也保留
# 手动 transfer
rcs = ua.transfer_subscriptions([sub.subscription_id], send_initial_values=True)
恢复流程
重连成功
↓
对每个本地 Subscription:
1. transfer_subscriptions(old_sub_id)
├─ GOOD → subscription_restored 事件, 完成
└─ BAD_SUBSCRIPTION_ID_INVALID → 进入 2
2. create_subscription(original_params) 拿新 sub_id
3. 按本地 _mi_cache 重建所有 MI
- SamplingInterval / Mode / QueueSize / DiscardOldest
- DataChangeFilter
- EventFilter
- Triggering Links
4. subscription_restored 事件
缓存的字段
_mi_cache 保留: NodeId / AttributeId / SamplingInterval / Mode / QueueSize / DiscardOldest / DataChangeFilter / EventFilter。
恢复时全部重放, 服务端 mi id 会变, 业务侧应使用 client_handle 而非 server-side id 对账。
最佳实践
- 业务用 client_handle, 不要持久化 mi id
- 监听 subscription_restored 事件, UI 显示 "已恢复, X 个监控项"
- 不要在 subscription_lost 里手动 recreate, SDK 已经在做
- 关键参数变更后 pause 再 resume
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| TransferSubscriptions | transfer_subscriptions | transferSubscriptions | TransferSubscriptions | transfer_subscriptions | DarraUa_Session_TransferSubscriptions |