You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js OPCUA如何在单个Subscription中批量添加多个Monitored Item

Node.js OPCUA批量订阅多个监控项的可行性问题

现有可运行代码

目前我已实现单个监控项的订阅逻辑,代码如下:

const itemToMonitor = {
    nodeId: resolveNodeId("ns=2;s=Channel1.Device1.temprature"),
    attributeId: AttributeIds.Value
};
const itemToMonitor2 = {
        nodeId: resolveNodeId("ns=2;s=Channel1.Device1.altitude"),
        attributeId: AttributeIds.Value
};
const monitoringParamaters = {
    samplingInterval: 1000,
    discardOldest: true
};
the_subscription.monitor(itemToMonitor, monitoringParamaters, TimestampsToReturn.Both, (err, monitoredItem) => {
    monitoredItem.on("changed", function (dataValue) {
        console.log("monitored item changed:  temprature = ", dataValue.value.value);
    });
});
the_subscription.monitor(itemToMonitor2, monitoringParamaters, TimestampsToReturn.Both, (err, monitoredItem) => {
    monitoredItem.on("changed", function (dataValue) {
        console.log("monitored item changed:  altitude = ", dataValue.value.value);
    });
});

期望实现的批量订阅方式

我希望能像以下伪代码这样,一次性批量订阅多个监控项,并在统一的回调中处理所有变更数据:

the_subscription.monitor({itemToMonitor,itemToMonitor2}, monitoringParamaters, TimestampsToReturn.Both, (err, monitoredItem) => {
            monitoredItem.on("changed", function (datavalues) {
                datavalues.each(){
                    // 批量处理所有变更数据
                }
            });
        });

.NET Core参考实现

我曾在.NET Core中实现过类似的批量订阅功能,参考代码如下:

_subscription.AddItems(_nodes);
_subscription.FastDataChangeCallback = new FastDataChangeNotificationEventHandler(DataChanged);
_session.AddSubscription(_subscription);
_subscription.Create();

private void DataChanged(Subscription subscription, DataChangeNotification notification, IList<string> stringTable)
{
  // 统一处理所有监控项的变更
}

可行性说明及实现方案

直接使用你伪代码中的monitor({itemToMonitor,itemToMonitor2})方式不可行,因为node-opcua的subscription.monitor()方法仅支持单个监控项配置作为第一个参数。但可以通过以下几种方式实现类似.NET Core的批量订阅效果:

方式1:循环创建+统一回调处理

将所有监控项整理为数组,循环调用monitor(),并绑定统一的变更处理逻辑:

// 整理监控项数组,附带节点名称用于识别
const monitoredItemConfigs = [
    { nodeId: resolveNodeId("ns=2;s=Channel1.Device1.temprature"), name: "temprature" },
    { nodeId: resolveNodeId("ns=2;s=Channel1.Device1.altitude"), name: "altitude" }
];

const monitoringParameters = {
    samplingInterval: 1000,
    discardOldest: true
};

// 统一的变更处理函数
const handleDataChange = (itemName, dataValue) => {
    console.log(`monitored item changed: ${itemName} = `, dataValue.value.value);
    // 此处可添加统一的数据处理逻辑
};

// 循环创建监控项
monitoredItemConfigs.forEach(config => {
    const itemToMonitor = {
        nodeId: config.nodeId,
        attributeId: AttributeIds.Value
    };
    the_subscription.monitor(itemToMonitor, monitoringParameters, TimestampsToReturn.Both, (err, monitoredItem) => {
        if (err) {
            console.error(`监控${config.name}失败:`, err);
            return;
        }
        monitoredItem.on("changed", (dataValue) => handleDataChange(config.name, dataValue));
    });
});

方式2:监听Subscription的dataChange事件

node-opcua的Subscription对象自带dataChange事件,订阅内任何监控项变更时都会触发该事件,回调会返回所有变更的监控项数据,与.NET Core的FastDataChangeCallback逻辑最接近:

// 先创建所有监控项
const itemToMonitor = { nodeId: resolveNodeId("ns=2;s=Channel1.Device1.temprature"), attributeId: AttributeIds.Value };
const itemToMonitor2 = { nodeId: resolveNodeId("ns=2;s=Channel1.Device1.altitude"), attributeId: AttributeIds.Value };

const monitoringParameters = { samplingInterval: 1000, discardOldest: true };

the_subscription.monitor(itemToMonitor, monitoringParameters, TimestampsToReturn.Both);
the_subscription.monitor(itemToMonitor2, monitoringParameters, TimestampsToReturn.Both);

// 批量处理所有变更
the_subscription.on("dataChange", (changedItems) => {
    changedItems.forEach(item => {
        const nodeIdStr = item.nodeId.toString();
        // 通过nodeId识别具体节点
        if (nodeIdStr === "ns=2;s=Channel1.Device1.temprature") {
            console.log("temprature changed: ", item.dataValue.value.value);
        } else if (nodeIdStr === "ns=2;s=Channel1.Device1.altitude") {
            console.log("altitude changed: ", item.dataValue.value.value);
        }
    });
});

方式3:高效批量创建(适合大量节点)

如果需要监控大量节点,推荐使用subscription.createMonitoredItems()方法,这是底层OPC UA协议的批量创建操作,比循环调用monitor()更高效:

const batchItems = [
    {
        itemToMonitor: { nodeId: resolveNodeId("ns=2;s=Channel1.Device1.temprature"), attributeId: AttributeIds.Value },
        monitoringMode: MonitoringMode.Reporting,
        requestedParameters: { samplingInterval: 1000, discardOldest: true }
    },
    {
        itemToMonitor: { nodeId: resolveNodeId("ns=2;s=Channel1.Device1.altitude"), attributeId: AttributeIds.Value },
        monitoringMode: MonitoringMode.Reporting,
        requestedParameters: { samplingInterval: 1000, discardOldest: true }
    }
];

the_subscription.createMonitoredItems(
    TimestampsToReturn.Both,
    batchItems,
    (err, results) => {
        if (err) {
            console.error("批量创建监控项失败:", err);
            return;
        }
        results.forEach((result, index) => {
            if (result.statusCode.isGood()) {
                result.monitoredItem.on("changed", (dataValue) => {
                    console.log(`第${index+1}个监控项变更:`, dataValue.value.value);
                });
            } else {
                console.error(`第${index+1}个监控项创建失败:`, result.statusCode.toString());
            }
        });
    }
);

内容的提问来源于stack exchange,提问作者rehdadth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 06:05:23