使用node-opcua监听EventPretreatDone事件失败,求替代Python脚本方案
解决node-opcua监听'EventPretreatDone'事件的问题
你的JavaScript代码无法接收事件的核心问题有以下几点:
- 未绑定事件回调来接收通知
- 监听的节点不正确,应该订阅服务器全局事件再过滤指定EventType
- EventFilter未包含必要字段,无法获取目标事件的
Message.Text - 缺少断开重连逻辑,无法保证连接稳定性
以下是修正后的完整实现,对齐Python脚本的功能:
const { OPCUAClient, ClientSubscription, EventFilter, AttributeIds, TimestampsToReturn, Variant } = require("node-opcua"); class EventListener { constructor(url) { this.url = url; this.client = OPCUAClient.create({ endpointMustExist: false }); this.session = null; this.subscription = null; } async start() { while (true) { try { console.log("Trying to connect..."); // 连接服务器 await this.client.connect(this.url); console.log("Connected"); // 创建会话 this.session = await this.client.createSession(); // 创建订阅 await this.createSubscription(); // 保持运行,监听事件 await new Promise(() => {}); // 阻塞直到断开 } catch (ex) { console.warn("Connection error:", ex.message); // 清理资源 await this.cleanup(); // 等待后重连 await new Promise(resolve => setTimeout(resolve, 500)); } } } async createSubscription() { this.subscription = ClientSubscription.create(this.session, { requestedPublishingInterval: 1000, requestedLifetimeCount: 100, requestedMaxKeepAliveCount: 10, maxNotificationsPerPublish: 100, publishingEnabled: true, priority: 10, }); // 监听订阅错误 this.subscription.on("error", (err) => { console.error("Subscription error:", err); this.cleanup(); }); // 监听订阅断开 this.subscription.on("terminated", () => { console.log("Subscription terminated"); this.cleanup(); }); // 配置事件过滤:只接收EventType为EventPretreatDone的事件 const filter = new EventFilter({ selectClauses: [ // 选择需要的事件字段,对应Python里的event.Message.Text等 { browsePath: [{ name: "EventType" }] }, { browsePath: [{ name: "Message" }, { name: "Text" }] }, { browsePath: [{ name: "ActiveState" }, { name: "id" }] }, { browsePath: [{ name: "ConditionName" }] }, ], whereClause: { elements: [ { filterOperator: "Equals", filterOperands: [ { type: "Literal", value: new Variant({ nodeId: "ns=1;s=EventPretreatDone" }) }, { type: "Attribute", attributeId: AttributeIds.EventType } ] } ] } }); // 监听服务器的EventNotifier节点(ns=0;i=2253是标准Server节点) const monitoredItem = this.subscription.monitor( { nodeId: "ns=0;i=2253", attributeId: AttributeIds.EventNotifier, }, { samplingInterval: 1000, filter: filter, queueSize: 10, discardOldest: true, }, TimestampsToReturn.Neither, ); // 接收事件通知 monitoredItem.on("event", (event) => { try { // 解析Message.Text,对应Python脚本的逻辑 const eventData = JSON.parse(event.message.text); console.log("Received EventPretreatDone:"); console.log("EventType:", event.eventType.toString()); console.log("Data:", JSON.stringify(eventData, null, 2)); } catch (parseErr) { console.error("Failed to parse event data:", parseErr); console.log("Raw event:", event); } }); console.log("Subscribed to events"); } async cleanup() { if (this.subscription) { await this.subscription.terminate(); this.subscription = null; } if (this.session) { await this.session.close(); this.session = null; } await this.client.disconnect(); } } // 启动监听 const listener = new EventListener("opc.tcp://10.0.6.107:4840"); listener.start().catch(console.error);
关键修正说明:
- 重连逻辑:通过循环尝试连接,断开后自动清理资源并重连,保持服务稳定性。
- 监听正确节点:订阅标准Server节点(
ns=0;i=2253)的EventNotifier属性,这是OPC UA服务器全局事件的入口,和Python脚本的subscribe_events()行为一致。 - 事件过滤:通过
whereClause指定只接收EventType为EventPretreatDone的事件,避免接收无关事件。 - 事件回调绑定:通过
monitoredItem.on("event")接收事件通知,解析message.text字段,对齐Python脚本的处理逻辑。 - 资源清理:在错误或断开时清理订阅、会话和连接,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Max M.
相关产品推荐
相关产品推荐

