首页 > 解决方案 > 服务器断开连接或使用 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;
}

但是,每当服务器重新启动或客户端和服务器之间的连接断开时,订阅就无法正常工作。

我可以添加会话活动侦听器,并且当连接断开时,像这样清除订阅管理器(星号之间的代码)。

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 的回复,我可以看到它应该自动完成,但每次服务器断开连接时我都会收到此消息(我的订阅日志和 statusCode):

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();

                }

它似乎可以工作,但我想知道这是最好的方法还是我错过了一些东西。谢谢大家的回答。

标签: javaopc-uamilo

解决方案


正确的方法主要是什么都不做——重新连接和重新订阅的所有细节都是自动处理的。

您需要处理的唯一情况是在创建新会话后无法传输订阅。实施SubscriptionListener::onSubscriptionTransferFailed以重新创建此回调指示传输失败的任何订阅。

实际上没有任何其他情况应该手动清除和重新创建订阅。onPublishFailure() 回调主要是信息性的,不需要操作。onSessionActive() 和 onSessionInactive() 仅供参考,不需要您采取任何行动。


推荐阅读