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

使用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);

关键修正说明:

  1. 重连逻辑:通过循环尝试连接,断开后自动清理资源并重连,保持服务稳定性。
  2. 监听正确节点:订阅标准Server节点(ns=0;i=2253)的EventNotifier属性,这是OPC UA服务器全局事件的入口,和Python脚本的subscribe_events()行为一致。
  3. 事件过滤:通过whereClause指定只接收EventType为EventPretreatDone的事件,避免接收无关事件。
  4. 事件回调绑定:通过monitoredItem.on("event")接收事件通知,解析message.text字段,对齐Python脚本的处理逻辑。
  5. 资源清理:在错误或断开时清理订阅、会话和连接,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Max M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:10:30