Node.js下OPC UA客户端多节点监控数据值缺失问题求助
问题:Node.js监控OPC UA多节点时值丢失
通过Node.js监控OPC UA多个节点时,发现多节点场景下无法获取节点的实际值,输出结果为监控项的元数据;但单节点监控时能正常拿到包含值的DataValue对象。
单节点监控代码
const parameters = { samplingInterval: 100, discardOldest: true, queueSize: 100, }; const itemToMonitor = { nodeId: nodeIdToMonitor, attributeId: AttributeIds.Value, }; const monitoredItem = await subscription.monitor( itemToMonitor, parameters, TimestampsToReturn.Both ); monitoredItem.on("changed", (dataValue) => { console.log(dataValue); });
单节点监控结果(正常)
DataValue { statusCode: ConstantStatusCode { _value: 0, _description: 'The operation succeeded.', _name: 'Good' }, sourceTimestamp: 2022-11-05T09:32:53.592Z { high_low: [ 30994681, -1803996084 ], picoseconds: 378800000 }, sourcePicoseconds: 378800000, serverTimestamp: 2022-11-05T09:46:55.741Z { high_low: [ 30994683, -1972436892 ], picoseconds: 757200000 }, serverPicoseconds: 757200000, value: Variant { dataType: 12, arrayType: 0, value: 'VALUE 1', dimensions: null } }
多节点监控代码(原异常代码)
const parameters = { samplingInterval: 100, discardOldest: true, queueSize: 100, }; const multiNodes = [{ nodeId:'ns=2;s=XXXXXXXX', attributeId: 13 },{ nodeId:'ns=2;s=YYYYYYYY', attributeId: 13 },{ nodeId:'ns=2;s=ZZZZZZZZ', attributeId: 13 }] const monitoredItem = await subscription.monitorItems( multiNodes, parameters, TimestampsToReturn.Both );
多节点监控下某节点的输出结果(异常)
<ref *1> ClientMonitoredItemImpl { _events: [Object: null prototype] { changed: [Function (anonymous)] }, _eventsCount: 1, _maxListeners: undefined, statusCode: ConstantStatusCode { _value: 0, _description: 'The operation succeeded.', _name: 'Good' }, subscription: ClientSubscriptionImpl { _events: [Object: null prototype] { error: [Function (anonymous)], started: [Function (anonymous)], keepalive: [Function (anonymous)], terminated: [Function (anonymous)] }, _eventsCount: 4, _maxListeners: undefined, monitoredItemGroups: [ [ClientMonitoredItemGroupImpl] ], timeoutHint: 15000, _nextClientHandle: 3, publishEngine: ClientSidePublishEngine { session: [ClientSessionImpl], subscriptionAcknowledgements: [Array], subscriptionMap: [Object], timeoutHint: 15000, activeSubscriptionCount: 1, nbPendingPublishRequests: 4, nbMaxPublishRequestsAcceptedByServer: 1000, isSuspended: false }, lastSequenceNumber: 1, publishingInterval: 250, lifetimeCount: 6000, maxKeepAliveCount: 50, maxNotificationsPerPublish: 1000, publishingEnabled: true, priority: 10, subscriptionId: 3904530469, monitoredItems: { '1': [Circular *1], '2': [ClientMonitoredItemImpl], '3': [ClientMonitoredItemImpl] }, lastRequestSentTime: 1906-06-23T23:00:00.000Z, hasTimedOut: false, [Symbol(kCapture)]: false }, itemToMonitor: ReadValueId { nodeId: NodeId { identifierType: 2, value: 'XXXXXXXX', namespace: 2 }, attributeId: 13, indexRange: NumericRange { type: 0, value: '<invalid>' }, dataEncoding: QualifiedName { namespaceIndex: 0, name: null } }, monitoringParameters: MonitoringParameters { clientHandle: 1, samplingInterval: 100, filter: null, queueSize: 100, discardOldest: true }, monitoringMode: 2, timestampsToReturn: 2, result: MonitoredItemCreateResult { statusCode: ConstantStatusCode { _value: 0, _description: 'The operation succeeded.', _name: 'Good' }, monitoredItemId: 1, revisedSamplingInterval: 100, revisedQueueSize: 100, filterResult: null }, monitoredItemId: 1, filterResult: undefined, [Symbol(kCapture)]: false }
问题原因与解决方法
核心原因
subscription.monitorItems()返回的是**ClientMonitoredItemImpl对象数组**,而非单个对象。原代码未为每个节点绑定changed事件,直接输出监控对象本身,导致显示的是节点元数据而非值变化。
修正后的多节点监控代码
const parameters = { samplingInterval: 100, discardOldest: true, queueSize: 100, }; const multiNodes = [{ nodeId:'ns=2;s=XXXXXXXX', attributeId: 13 },{ nodeId:'ns=2;s=YYYYYYYY', attributeId: 13 },{ nodeId:'ns=2;s=ZZZZZZZZ', attributeId: 13 }] // monitorItems返回数组,需接收为数组类型 const monitoredItems = await subscription.monitorItems( multiNodes, parameters, TimestampsToReturn.Both ); // 遍历每个监控项,单独绑定changed事件 monitoredItems.forEach(item => { item.on("changed", (dataValue) => { // 通过nodeId区分不同节点,输出包含实际值的DataValue console.log(`节点 ${item.itemToMonitor.nodeId.value} 变化值:`, dataValue); }); });
修正后即可和单节点场景一致,在值变化时获取到包含具体值的DataValue对象。
内容的提问来源于stack exchange,提问作者user1636103
相关产品推荐
相关产品推荐

