服务器断开连接或使用 OPC UA milo 重新启动后如何处理重新订阅?
How to handle resubscribing after server is disconnected or restarted with OPC UA milo?
您好,我想知道如何(正确)处理 OPC UA milo 的重新订阅。目前我使用此代码创建订阅:
private CompletableFuture<DataValue> subscribe(NodeId nodeToSubscribe, double samplingInterval, Consumer<DataValue> onChangeDo){
CompletableFuture<DataValue> result = new CompletableFuture<>();
try{
//sets parameters of subscription
ManagedSubscription subscription = ManagedSubscription.create(client, samplingInterval);
subscription.setDefaultSamplingInterval(samplingInterval);
subscription.setDefaultQueueSize(uint(10));
//adds "onChange" action
ManagedDataItem managedDataItem = subscription.createDataItem(nodeToSubscribe, item -> item.addDataValueListener(onChangeDo));
//wait till first value was read
ManagedDataItem.DataValueListener listener = managedDataItem.addDataValueListener(result::complete);
result.whenComplete((v,e) -> managedDataItem.removeDataValueListener(listener));
} catch (UaException e){
result.completeExceptionally(e);
}
return result;
}
但是每当服务器重新启动或客户端与服务器之间的连接断开时,订阅就无法正常工作。
我可以添加会话 activity 侦听器,每当连接中断时,都可以像那样清除订阅管理器(星号之间的代码)。
addSessionActivityListener(new SessionActivityListener(){
@Override
public void onSessionActive(UaSession session) {
log.info("Connecting PLC with IP address {}",ipAddress);
setConnectionStatus(ConnectionStatus.CONNECTED);
**subscribeAll();**
}
@Override
public void onSessionInactive(UaSession session) {
log.info("Disconnecting PLC with IP address {}",ipAddress);
setConnectionStatus(ConnectionStatus.DISCONNECTED);
**uaClient.getSubscriptionManager().clearSubscriptions();**
}
});
但也许有更好的方法来处理这个问题。我的所有代码都可以在这里找到 GitHub
更新:
根据 Kevin Harron 的回复,我可以看到它应该自动完成,但每次服务器断开连接时我都会收到此消息(我的订阅日志和状态代码):
ON SUBSCRIPTION TRANSFER FAILED: subscription org.eclipse.milo.opcua.sdk.client.subscriptions.OpcUaSubscription@3f344a79, status code StatusCode{name=Bad_ServiceUnsupported, value=0x800B0000, quality=bad}
如您所见,可能存在问题,该服务器不支持订阅转移。凯文建议我应该使用 SubscriptionListener::onSubscriptionTransferFailed
来处理,所以我这样实现:
uaClient.getSubscriptionManager().addSubscriptionListener(new UaSubscriptionManager.SubscriptionListener() {
@Override
public void onSubscriptionTransferFailed(UaSubscription subscription, StatusCode statusCode) {
uaClient.getSubscriptionManager().clearSubscriptions();
subscribeAll();
}
它似乎可以工作,但我想知道这是不是最好的方法,或者我错过了什么。谢谢大家的回答。
正确的方法主要是什么都不做 - 重新连接和重新订阅的所有细节都是自动处理的。
您唯一需要处理的情况是在创建新会话后无法转移订阅。实施 SubscriptionListener::onSubscriptionTransferFailed
以重新创建此回调指示传输失败的任何订阅。
实际上没有任何其他情况需要您手动清除并重新创建您的订阅。 onPublishFailure() 回调主要是信息性的,不需要采取任何行动。 onSessionActive() 和 onSessionInactive() 仅供参考,不需要您采取任何行动。
您好,我想知道如何(正确)处理 OPC UA milo 的重新订阅。目前我使用此代码创建订阅:
private CompletableFuture<DataValue> subscribe(NodeId nodeToSubscribe, double samplingInterval, Consumer<DataValue> onChangeDo){
CompletableFuture<DataValue> result = new CompletableFuture<>();
try{
//sets parameters of subscription
ManagedSubscription subscription = ManagedSubscription.create(client, samplingInterval);
subscription.setDefaultSamplingInterval(samplingInterval);
subscription.setDefaultQueueSize(uint(10));
//adds "onChange" action
ManagedDataItem managedDataItem = subscription.createDataItem(nodeToSubscribe, item -> item.addDataValueListener(onChangeDo));
//wait till first value was read
ManagedDataItem.DataValueListener listener = managedDataItem.addDataValueListener(result::complete);
result.whenComplete((v,e) -> managedDataItem.removeDataValueListener(listener));
} catch (UaException e){
result.completeExceptionally(e);
}
return result;
}
但是每当服务器重新启动或客户端与服务器之间的连接断开时,订阅就无法正常工作。
我可以添加会话 activity 侦听器,每当连接中断时,都可以像那样清除订阅管理器(星号之间的代码)。
addSessionActivityListener(new SessionActivityListener(){
@Override
public void onSessionActive(UaSession session) {
log.info("Connecting PLC with IP address {}",ipAddress);
setConnectionStatus(ConnectionStatus.CONNECTED);
**subscribeAll();**
}
@Override
public void onSessionInactive(UaSession session) {
log.info("Disconnecting PLC with IP address {}",ipAddress);
setConnectionStatus(ConnectionStatus.DISCONNECTED);
**uaClient.getSubscriptionManager().clearSubscriptions();**
}
});
但也许有更好的方法来处理这个问题。我的所有代码都可以在这里找到 GitHub
更新: 根据 Kevin Harron 的回复,我可以看到它应该自动完成,但每次服务器断开连接时我都会收到此消息(我的订阅日志和状态代码):
ON SUBSCRIPTION TRANSFER FAILED: subscription org.eclipse.milo.opcua.sdk.client.subscriptions.OpcUaSubscription@3f344a79, status code StatusCode{name=Bad_ServiceUnsupported, value=0x800B0000, quality=bad}
如您所见,可能存在问题,该服务器不支持订阅转移。凯文建议我应该使用 SubscriptionListener::onSubscriptionTransferFailed
来处理,所以我这样实现:
uaClient.getSubscriptionManager().addSubscriptionListener(new UaSubscriptionManager.SubscriptionListener() {
@Override
public void onSubscriptionTransferFailed(UaSubscription subscription, StatusCode statusCode) {
uaClient.getSubscriptionManager().clearSubscriptions();
subscribeAll();
}
它似乎可以工作,但我想知道这是不是最好的方法,或者我错过了什么。谢谢大家的回答。
正确的方法主要是什么都不做 - 重新连接和重新订阅的所有细节都是自动处理的。
您唯一需要处理的情况是在创建新会话后无法转移订阅。实施 SubscriptionListener::onSubscriptionTransferFailed
以重新创建此回调指示传输失败的任何订阅。
实际上没有任何其他情况需要您手动清除并重新创建您的订阅。 onPublishFailure() 回调主要是信息性的,不需要采取任何行动。 onSessionActive() 和 onSessionInactive() 仅供参考,不需要您采取任何行动。