rxhulcm
rxhulcm

Reputation: 21

Issue with subscription handling multiple nodeids

I've wrote code for OPC UA client that has 10 subscription each handling 3 nodeids. Even though monitored items are being created for every node id, the subscription only receives value from the last nodeid in each subscription.

public static void main(String[] args) throws Exception {
    OpcUaClient client = OpcUaClient.create("opc.tcp://KCT-L-610:53530/OPCUA/SimulationServer"); // Update with your Prosys OPC UA Server endpoint
    client.connect().get();

    // Create 10 subscriptions, each handling 3 tags
    for (int i = 0; i < 10; i++) {
        createSubscription(client, i);
    }

    // Sleep to allow subscriptions to run and collect data
    Thread.sleep(10000); // Example: run for 10 seconds before completing
    client.disconnect().get();
}

private static void createSubscription(OpcUaClient client, int subscriptionIndex) throws Exception {
    // Create a new subscription every time
    UaSubscription subscription = client.getSubscriptionManager().createSubscription(1000.0).get();

    // Define the 3 tags (nodes) to monitor for this subscription
    List<ReadValueId> readValueIds = newArrayList(
        new ReadValueId(new NodeId(3, 1007 + subscriptionIndex * 3), AttributeId.Value.uid(), null, QualifiedName.NULL_VALUE),  // Tag 1 for Subscription
        new ReadValueId(new NodeId(3, 1008 + subscriptionIndex * 3), AttributeId.Value.uid(), null, QualifiedName.NULL_VALUE),  // Tag 2 for Subscription
        new ReadValueId(new NodeId(3, 1009 + subscriptionIndex * 3), AttributeId.Value.uid(), null, QualifiedName.NULL_VALUE)   // Tag 3 for Subscription
    );

    // Create a MonitoringParameters object for the subscription
    MonitoringParameters parameters = new MonitoringParameters(
        subscription.nextClientHandle(),
        1000.0, // Sampling interval: 1 second
        null,   // No filter, use default
        uint(10),  // Queue size
        true    // Discard oldest value if queue is full
    );
    
    // Create requests for the monitored items
    List<MonitoredItemCreateRequest> requests = newArrayList();
    for (ReadValueId readValueId : readValueIds) {
        requests.add(new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting, parameters));
    }

    // Create the monitored items and set a callback for value updates
    //UaSubscription.ItemCreationCallback onItemCreated = (item, id) -> item.setValueConsumer((item1, value) -> onSubscriptionValue(item1, value, subscriptionIndex));
    UaSubscription.ItemCreationCallback onItemCreated = (item, id) -> {
        item.setValueConsumer((item1, value) -> onSubscriptionValue(item1, value, subscriptionIndex));
    };

    // Create monitored items and process
    List<UaMonitoredItem> items = subscription.createMonitoredItems(
        TimestampsToReturn.Both,
        requests,
        onItemCreated
    ).get();

    for (UaMonitoredItem item : items) {
        if (item.getStatusCode().isGood()) {
            logger.info("Subscription {}: Monitored item created for nodeId={}", subscriptionIndex, item.getReadValueId().getNodeId());
        } else {
            logger.warn("Subscription {}: Failed to create item for nodeId={} (status={})", subscriptionIndex, item.getReadValueId().getNodeId(), item.getStatusCode());
        }
    }
}

private static void onSubscriptionValue(UaMonitoredItem item, DataValue value, int subscriptionIndex) {
    // This method is called when the monitored item value is updated
    logger.info("Subscription {}: Received value for nodeId={}: {}", subscriptionIndex, item.getReadValueId().getNodeId(), value.getValue());
}

and this was the output i was getting

14:56:45.402 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 0: Received value for nodeId=NodeId{ns=3, id=1009}: Variant{value=0.0}
14:56:45.403 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 0: Received value for nodeId=NodeId{ns=3, id=1009}: Variant{value=-1.618126}
14:56:45.403 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 0: Received value for nodeId=NodeId{ns=3, id=1009}: Variant{value=-2.0}
14:56:45.413 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 1: Received value for nodeId=NodeId{ns=3, id=1012}: Variant{value=0.1333334}
14:56:45.417 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 1: Received value for nodeId=NodeId{ns=3, id=1012}: Variant{value=27.0}
14:56:45.417 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 1: Received value for nodeId=NodeId{ns=3, id=1012}: Variant{value=0.0}
14:56:45.417 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 1: Received value for nodeId=NodeId{ns=3, id=1012}: Variant{value=28.0}
14:56:45.427 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 2: Received value for nodeId=NodeId{ns=3, id=1015}: Variant{value=-5.235019}
14:56:45.427 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 2: Received value for nodeId=NodeId{ns=3, id=1015}: Variant{value=0.209057}
14:56:45.427 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 2: Received value for nodeId=NodeId{ns=3, id=1015}: Variant{value=-4.472503}
14:56:45.427 [milo-shared-thread-pool-3] INFO  c.m.o.MultipleSubscriptionExample - Subscription 2: Received value for nodeId=NodeId{ns=3, id=1015}: Variant{value=0.0}

Upvotes: 1

Views: 33

Answers (1)

Kevin Herron
Kevin Herron

Reputation: 6985

You are erroneously re-using the same MonitoringParameters for each group of 3 items you create, rather than creating a new one, which is necessary because each parameters should contain a unique client handle.

// Create a MonitoringParameters object for the subscription
MonitoringParameters parameters = new MonitoringParameters(
    subscription.nextClientHandle(),
    1000.0, // Sampling interval: 1 second
    null,   // No filter, use default
    uint(10),  // Queue size
    true    // Discard oldest value if queue is full
); 

// Create requests for the monitored items
List<MonitoredItemCreateRequest> requests = newArrayList();
for (ReadValueId readValueId : readValueIds) {
    requests.add(new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting, parameters));
}

Upvotes: 0

Related Questions