当前位置: 首页 > news >正文

学习OPC UA,连接OPC UA服务器

流程图

服务端

​import {OPCUAServer,DataType,
} from "node-opcua";const SERVER_PORT = 4840;
const RESOURCE_PATH = "";  
async function createTestServer() {try {const server = new OPCUAServer({port: SERVER_PORT,resourcePath: RESOURCE_PATH,buildInfo: {productName: "PLC Simulator",buildNumber: "1.0.0",buildDate: new Date(),manufacturerName: "Test Environment"}});await server.initialize();console.log("✓ 服务器初始化完成");// ============================================================// 第一步:获取地址空间(理解为打开一个文件系统)// ============================================================const addressSpace = server.engine.addressSpace;if (!addressSpace) {console.error("❌ 错误:无法获取地址空间");throw new Error("无法获取地址空间");}console.log("✓ 地址空间获取成功");// 获取命名空间(你的专属区域,不会和其他厂商冲突)const namespace = addressSpace.getOwnNamespace();const namespaceIndex = namespace.index;console.log(`✓ 命名空间获取成功 (ns=${namespaceIndex})`);// ============================================================// 第二步:创建"对象"(相当于创建一个文件夹)// ============================================================// 创建一个名为 "Machine" 的对象(文件夹)// 这个对象本身不存储数据,只是用来组织下面的变量const machineDevice = namespace.addObject({organizedBy: addressSpace.rootFolder.objects,  // 放在根目录的 Objects下browseName: "Machine",                         // 显示名称:MachinenodeId: "s=Machine"                 // 相对 nodeId(自动使用当前命名空间)});console.log("✓ Machine 对象创建成功");// ============================================================// 第四步:在 Machine 对象里添加变量(相当于在文件夹里创建文件)// =============================================================namespace.addVariable({componentOf: machineDevice,    // 放在 Machine 对象(文件夹)里browseName: "TEST",              // 显示名称:TESTnodeId: "s=Machine.TEST",        // 相对 nodeIddataType: "Double",            // 数据类型:双精度浮点数value: {dataType: DataType.Double, value: 6.01}});console.log(`✓ TEST 变量创建成功`);// ============================================================// 最终结构:// Root///   └── Objects///       └── Machine/              (对象 - 文件夹)//           ├── TEST = 6.01        (变量 - 文件,存储周向电流)// ============================================================// 启动服务器await server.start();const endpointUrl = server.endpoints[0].endpointDescriptions()[0].endpointUrl;console.log(`\n📡 服务器端点: ${endpointUrl}`);console.log(`🔌 可用节点:`);console.log(`   • ns=${namespaceIndex};s=Machine.TEST`);process.on("SIGINT", async () => {console.log("\n\n正在关闭服务器...");await server.shutdown();console.log("✓ 服务器已安全关闭\n");process.exit(0);});} catch (err) {console.error("\n❌ 服务器启动失败:", err);process.exit(1);}
}
// 启动服务器
createTestServer();

客户端

​
import {OPCUAClient,MessageSecurityMode,SecurityPolicy,AttributeIds,StatusCodes,ClientSession,DataValue
} from 'node-opcua';// 固定的 OPC UA 配置
const OPCUA_ENDPOINT_URL = "opc.tcp://127.0.0.1:4840";
const OPCUA_TEST_NODE_ID = "ns=1;s=Machine.TEST";class OpcUaClient {private client: any = null;private session: ClientSession | null = null;/*** 初始化 OPC UA 客户端,连接服务器,创建会话*/public async initialize() {try {// 创建客户端实例this.client = OPCUAClient.create({applicationName: 'PLCClient',securityMode: MessageSecurityMode.None,securityPolicy: SecurityPolicy.None,endpoint_must_exist: false,connectionStrategy: {initialDelay: 1000,maxRetry: 3}});// 连接服务器await this.client.connect(OPCUA_ENDPOINT_URL);// 创建会话this.session = await this.client.createSession();} catch (err) {console.error('[OpcUaClient] Initialize failed:', err);await this.cleanup();}}/*** 读取 TEST 数据*/public async readData() {if (!this.session) {try {await this.initialize();} catch (_e) {console.error('[OpcUaClient] Failed to initialize:', _e);}if (!this.session) return;}try {// 直接读取TEST节点const read ={nodeId: OPCUA_TEST_NODE_ID,attributeId: AttributeIds.Value}// 批量读取const dataValue: DataValue = await this.session.read(read);let value = 0;// 处理 TEST 值if (dataValue.statusCode === StatusCodes.Good) {value = dataValue.value?.value ?? 0;} else {console.warn(`[OpcUaClient] Failed to read REST:`, dataValue.statusCode.toString());}return value;} catch (err) {console.error('[OpcUaClient] Read data error:', err);try {await this.cleanup();await this.initialize();} catch (_e) {console.error('[OpcUaClient] Failed to initialize:', _e);}return;}}/*** 清理资源*/private async cleanup() {// 关闭会话if (this.session) {try {await this.session.close();} catch (err) {console.error('[OpcUaClient] Failed to close session:', err);}this.session = null;}// 断开连接if (this.client) {try {await this.client.disconnect();} catch (err) {console.error('[OpcUaClient] Failed to disconnect:', err);}this.client = null;}}
}

http://www.dtcms.com/a/592499.html

相关文章:

  • 从零开始:构建你的第一个MCP服务器
  • 数据结构之二叉树-堆
  • BridgeVLA 对比 pi 0.5 有提升吗
  • 深度学习 :python水下海洋生物识别检测系统 Yolo模型 PyTorch框架 计算机 ✅
  • COM_QueryInterface
  • DeepSeek-OCR全面解析:技术原理、性能优势与实战指南
  • WebKit Insie: WebKit 调试(二)
  • 网站建设需求材料推广网店的途径和方法
  • 排名优化网站沈阳中小企业网站制作
  • 从0到1:兰亭妙微如何用“小程序思维”重构用户体验路径
  • AI重构天猫双11,一场新的效率革命
  • 智慧园区:数字中国的“微缩实验室”如何重构城市未来
  • 新技术如何重构AI营销获客的底层逻辑与竞争格局
  • [论文阅读] AI+ | AI重构工业数字孪生!新一代iDTS破解数据稀缺、智能不足难题,附3大落地案例
  • 京东的一次范围经济尝试,却改变了汽车营销游戏规则
  • 圆柱电池Pack生产线的极性与质量守护:视觉检测系统把好安全关
  • 【大数据技术03】机器学习与算法
  • A模块 系统与网络安全 第四门课 弹性交换网络-6
  • it之家网站源码wordpress门户主体
  • 浏览器访问web服务器经过了哪些过程
  • 时序数据库系列(七):性能监控实战指标收集
  • 【数据库】分布式事务篇
  • 《Windows 11 + Docker:极简DVWA靶场搭建全记录》—— 附详细排错指南与最终解决方案
  • 时序数据库系列(八):InfluxDB配合Grafana可视化
  • M3部署vllm
  • 仿新浪全站网站源码公司简介电子版宣传册模板
  • 在 Lit 应用中实现响应式布局
  • 零基础学AI大模型之向量数据库介绍与技术选型思考
  • 三次更名的背后:百度AI的定位困惑
  • StreamingT2V:从文本生成一致、动态和可扩展的长视频