假设有 3 个节点要订阅数据更改(这些数据会自动存储在 asyncua 提供的 self._monitored_items() 字典中),在这种情况下,如果任何节点在一段时间内不可用,然后再次可用,那么客户端如何知道该节点恢复在线了吗?
async with client:
# We create a Client Subscription.
subscription = await client.create_subscription(50, handler)
nodes = [
client.get_node('ns=3;i=1025'),
client.get_node('ns=3;i=1026'),
client.get_node('ns=3;i=1027')
]
handle = await subscription.subscribe_data_change(nodes)
print(subscription._monitored_items)
我尝试使用 read_value 方法,它会定期检查每个节点的值,如果我们得到值,则意味着该节点可用......但这里的问题是,如果我的检查周期为 10 秒,并且该节点变为前 2 秒可用,8 秒数据丢失。
async def check_node_availability(node):
""" Check if the node is still available on the server by reading its value. """
try:
await node.read_value()
return True
except Exception as e:
# print(f'Failed to read node {node}: {e}')
return False
如何防止上述数据丢失?
OPC UA 客户端不需要关心这一点。
当受监控的节点消失时,OPC UA 服务器应报告 Bad_NodeIdUnknown 状态,并在节点重新出现时自动继续报告值。
Subscription 和 MonitoredItem 可以一直保持活动状态。
如果服务器没有这样的行为,那么看看服务器是否支持 ModelChangeEvents。 当节点或引用出现或消失时,服务器可以报告 ModelChangeEvents。 客户端可以订阅 ModelChangeEvent 并接收节点发生变化的信息。 对于任何事件订阅,可以在任何事件传播节点上订阅事件,例如:父对象、文件夹或“服务器”节点上接收所有事件。
如果前面的方法都不起作用,那么循环读取似乎是唯一的解决方案。