关于OPC-UA客户端调用服务端方法CallMethod节点的问题

在OpcUaClient中可以通过CallMethodByNodeId调用方法节点

        //// 摘要://     call a server method//// 参数://   tagParent://     方法的父节点tag////   tag://     方法的节点tag////   args://     传递的参数//// 返回结果://     输出的结果值public object[] CallMethodByNodeId(string tagParent, string tag, params object[] args);

注意,调用方法节点时,必须传入指定的参数类型的值,不能传入可以隐式转化的实参

比如在OpcServer服务器上有个方法节点,方法名为readJob,需要传入两个参数 (byte sourceNumber, short jobNo),返回一个工作名称string jobName
       方法整体描述为 string readJob(byte sourceNumber, short jobNo)

传入的实参 new object[]{1,23};会抛出异常,因1和23在C#中是Int32类型,不是byte,short类型

如果需要调用成功,传入的实参必须是new object[]{(byte)1, (short)23};

一、新建Winform应用程序OpcUaCallMethodDemo,将默认的Form1修改为FormOpcUaCallMethod。

并添加Opc客户端类库的引用以及其他必须相关类库文件。

OpcUaHelper.dll

Opc.Ua.Core.dll

Opc.Ua.Client.dll

二、新建类GumOpcUaClientUtil,用于连接Opc服务已经读写标签,调用Opc方法等

GumOpcUaClientUtil.cs源代码下:

using Opc.Ua;
using OpcUaHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace OpcUaCallMethodDemo
{/// <summary>/// 涂胶OPC客户端:连接OPC服务端,读、写标签操作/// </summary>public class GumOpcUaClientUtil{/// <summary>/// 定义一个操作OPC的客户端对象/// </summary>private static OpcUaClient m_OpcUaClient = new OpcUaClient();/// <summary>/// 连接到Opc服务端/// </summary>/// <param name="serverAddress"></param>/// <param name="enabledAnonymousLogin"></param>/// <param name="loginUserName"></param>/// <param name="loginPassword"></param>/// <returns></returns>public static bool ConnectOpcServer(string serverAddress, bool enabledAnonymousLogin, string loginUserName, string loginPassword, Action<string> LogToShow){bool isConnected = false;if (enabledAnonymousLogin){//匿名登录m_OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken());}else{//用户名密码登录m_OpcUaClient.UserIdentity = new UserIdentity(loginUserName, loginPassword);}try{LogToShow($"准备连接OPC服务端【{serverAddress}】,匿名登录【{enabledAnonymousLogin}】,用户名【{loginUserName}】,密码【{loginPassword}】");Task task = m_OpcUaClient.ConnectServer(serverAddress);task.Wait(5000);isConnected = m_OpcUaClient.Connected;//HansCommon.SysMsg.MySystemMsg.LogToShow($"获取到 连接OPC服务端【{serverAddress}】结果:{isConnected}", true);}catch (Exception ex){string exMsg = $"连接OPC服务【{serverAddress}】失败,错误原因:{ex.Message}";LogToShow(exMsg);MessageBox.Show(exMsg, "错误");}return isConnected;}/// <summary>/// 断开OPC服务/// </summary>public static void Disconnect(){m_OpcUaClient.RemoveAllSubscription();m_OpcUaClient.Disconnect();}/// <summary>/// 调用OPC的方法/// </summary>/// <param name="tagParent">方法的父标签路径</param>/// <param name="methodName">方法的标签全路径</param>/// <param name="args">参数列表,没有参数请输入null</param>/// <returns></returns>public static object[] CallMethodNode(Action<string> LogToShow, string tagParent, string methodName, params object[] args) {try{object[] methodResult = m_OpcUaClient.CallMethodByNodeId(tagParent, methodName, args);return methodResult;}catch (Exception ex){MessageBox.Show(ex.Message);LogToShow($"调用OPC的方法时出错{ex.Message}");return null;}}/// <summary>/// 读取某一个标签/// </summary>/// <typeparam name="T"></typeparam>/// <param name="tagName"></param>/// <returns></returns>public static bool ReadTagNode<T>(string tagName, Action<string> LogToShow, out T tResult){tResult = default(T);DataValue dataValue = m_OpcUaClient.ReadNode(new NodeId(tagName));if (dataValue == null || dataValue.WrappedValue == Variant.Null){string exMsg = $"[{tagName}]项读取失败,可能是①未连接的opc服务或者连接已断开.②标签路径或数据类型设置错误,注意:标签名区分大小写.③没有权限读取数据";LogToShow(exMsg);return false;}else{object objValue = dataValue.WrappedValue.Value;tResult = (T)objValue;}return true;}public static object ReadTagNode(string tagName, Action<string> LogToShow){DataValue dataValue = m_OpcUaClient.ReadNode(new NodeId(tagName));if (dataValue == null || dataValue.WrappedValue == Variant.Null){string exMsg = $"[{tagName}]项读取失败,可能是①未连接的opc服务或者连接已断开.②标签路径或数据类型设置错误,注意:标签名区分大小写.③没有权限读取数据";LogToShow(exMsg);return null;}else{object objValue = dataValue.WrappedValue.Value;return objValue;}}/// <summary>/// 批量读取/// </summary>/// <typeparam name="T"></typeparam>/// <param name="tagNames"></param>/// <returns></returns>public static List<T> ReadNodeList<T>(string[] tagNames, Action<string> LogToShow){try{List<T> list = m_OpcUaClient.ReadNodes<T>(tagNames);return list;}catch (Exception ex){string exMsg = $"批量读取节点集合出错【{string.Join(",", tagNames)}】,可能是①未连接的opc服务或者连接已断开.②存在标签路径或数据类型设置错误,注意:标签名区分大小写.③没有权限读取数据.异常信息:{ex.Message}";LogToShow(exMsg);throw new Exception(exMsg);}}/// <summary>/// 为指定的标签写入指定类型的值。注意:【写入的标签名 和 写入的值的类型一定要和服务端保持一致】/// </summary>/// <typeparam name="T"></typeparam>/// <param name="tagName"></param>/// <param name="value"></param>/// <returns></returns>public static bool WriteTagNode<T>(string tagName, Action<string> LogToShow, T value){try{return m_OpcUaClient.WriteNode(tagName, value);}catch (Exception ex){string exMsg = $"【{tagName}】项写入【{value}】失败,【写入的标签名 和 写入的值的类型一定要和服务端保持一致】.异常信息:{ex.Message}";LogToShow(exMsg);throw new Exception(exMsg);}}}
}

三、窗体FormOpcUaCallMethod设计器代码如下:

文件FormOpcUaCallMethod.Designer.cs


namespace OpcUaCallMethodDemo
{partial class FormOpcUaCallMethod{/// <summary>/// 必需的设计器变量。/// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// 清理所有正在使用的资源。/// </summary>/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗体设计器生成的代码/// <summary>/// 设计器支持所需的方法 - 不要修改/// 使用代码编辑器修改此方法的内容。/// </summary>private void InitializeComponent(){this.rtxtMessage = new System.Windows.Forms.RichTextBox();this.btnConnect = new System.Windows.Forms.Button();this.SuspendLayout();// // rtxtMessage// this.rtxtMessage.Location = new System.Drawing.Point(249, 12);this.rtxtMessage.Name = "rtxtMessage";this.rtxtMessage.ReadOnly = true;this.rtxtMessage.Size = new System.Drawing.Size(700, 495);this.rtxtMessage.TabIndex = 0;this.rtxtMessage.Text = "";// // btnConnect// this.btnConnect.Location = new System.Drawing.Point(27, 72);this.btnConnect.Name = "btnConnect";this.btnConnect.Size = new System.Drawing.Size(152, 36);this.btnConnect.TabIndex = 1;this.btnConnect.Text = "连接Opc服务端并测试";this.btnConnect.UseVisualStyleBackColor = true;this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);// // FormOpcUaCallMethod// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1018, 531);this.Controls.Add(this.btnConnect);this.Controls.Add(this.rtxtMessage);this.Name = "FormOpcUaCallMethod";this.Text = "使用OpcUaCallMethod调用OpcServer的方法节点";this.ResumeLayout(false);}#endregionprivate System.Windows.Forms.RichTextBox rtxtMessage;private System.Windows.Forms.Button btnConnect;}
}

窗体FormOpcUaCallMethod代码如下:

文件FormOpcUaCallMethod.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace OpcUaCallMethodDemo
{public partial class FormOpcUaCallMethod : Form{public FormOpcUaCallMethod(){InitializeComponent();}/// <summary>/// 显示推送消息/// </summary>/// <param name="msg"></param>private void DisplayMessage(string msg){this.BeginInvoke(new Action(() =>{if (rtxtMessage.TextLength > 409600){rtxtMessage.Clear();}rtxtMessage.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}->{msg}\n");rtxtMessage.ScrollToCaret();}));}private void btnConnect_Click(object sender, EventArgs e){//连接OPC服务端string serverAddress = "opc.tcp://192.168.1.20:48030";bool isRun = GumOpcUaClientUtil.ConnectOpcServer(serverAddress, false, "admin", "password123456", DisplayMessage);DisplayMessage($"连接OPC服务端【{serverAddress}】:{(isRun ? "成功" : "失败")}");if (!isRun){DisplayMessage($"连接OPC服务端【{serverAddress}】失败,无法启动");return;}string parentNodeTag = "ns=2;s=A.B.C.ParentTag";string methodNode = "ns=2;s=A.B.C.ParentTag.readJob";//在OpcServer服务器上有个方法节点,方法名为readJob,需要传入两个参数 (byte sourceNumber, short jobNo),返回一个工作名称string jobName//方法整体描述为 string readJob(byte sourceNumber, short jobNo)short jobNo = 12;object[] resultArray = GumOpcUaClientUtil.CallMethodNode(DisplayMessage, parentNodeTag, methodNode, new object[] { (byte)1, jobNo });if (resultArray == null || resultArray.Length < 1){DisplayMessage($"读取readJob节点出错,低于1个元素,当前工作编号为【{jobNo}】");}else{DisplayMessage($"读取readJob节点成功,返回信息【{resultArray[0]}】,当前工作编号为【{jobNo}】");}}}
}

四、测试如图:

【没有连接Opc服务端】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/747235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

栈与队列|232.用栈实现队列

力扣题目链接 class MyQueue { public:stack<int> stIn;stack<int> stOut;/** Initialize your data structure here. */MyQueue() {}/** Push element x to the back of queue. */void push(int x) {stIn.push(x);}/** Removes the element from in front of que…

数据结构--线性表

1.线性表的定义&#xff1a; 存在唯一的一个被称为“第一个”的数据元素&#xff1b; 存在唯一的一个被称为“最后一个”的数据元素&#xff1b; 除第一个之外&#xff0c;集合中的每一个数据元素都只有一个前驱&#xff1b; 除最后一个之外&#xff0c;集合中的每一个数据…

大话设计模式——7.抽象工厂模式(Abstract Factory Pattern)

1.介绍 抽象工厂模式是工厂模式的进一步优化&#xff0c;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。属于创建型模式。 UML图&#xff1a; 2.示例 车辆制造工厂&#xff0c;不仅可以制造轿车也可以用来生产自行车。 1&#xff09;Abs…

vivado 逻辑优化约束、功率优化、Vivado Tools电源优化

逻辑优化约束 逻辑保护 Vivado设计套件在逻辑优化过程中尊重DONT_TOUCH属性。确实如此不优化具有这些特性的离开网或单元。为了加快网络选择过程&#xff0c;网络具有DONT_TOUCH的属性被预过滤并且不被考虑用于物理优化。对于有关详细信息&#xff0c;请参阅《Vivado Design …

10、MongoDB -- MongoDB 的 MongoTemplate 的功能和用法介绍

目录 MongoTemplate 的功能和用法演示前提&#xff1a;登录单机模式的 mongodb 服务器命令登录【test】数据库的 mongodb 客户端命令登录【admin】数据库的 mongodb 客户端命令 为 MongoDB 提供的两个 Starterspring-boot-starter-data-mongodb&#xff08;为以同步方式操作 Mo…

C语言:操作符详解(下)

目录 一、逗号表达式二、下标访问[ ]、函数调用()1. [ ]下标引用操作符2.函数调用操作符 三、结构成员访问操作符1.结构体(1) 结构的声明(2) 结构体变量的定义和初始化 2.结构成员访问操作符(1)结构体成员的直接访问(2)结构体成员的间接访问 四、操作符的属性&#xff1a;优先级…

深入理解JMM

一、什么是JMM JMM&#xff08;java memory model&#xff09;Java内存模型&#xff1a;是java虚拟机规范中定义的一组规范&#xff0c;用于屏蔽掉各种硬件和操作系统的内存访问差异&#xff0c;以实现让JAVA程序在各平台都能达到一致的并发结果。其主要规定了线程和内存之间的…

对称加密算法(DES、AES)

加密密钥 解密密钥 DES现在基本不再使用 3DES处理速度慢 AES通常用于移动通信系统加密以及基于SSH协议的软件

c++入门你需要知道的知识点(上)

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;c入门 主厨&#xff1a;邪王真眼 所属专栏&#xff1a;c专栏 主厨的主页&#xff1a;Chef‘s blog 前言&#xff1a; 咱也是好久没有更…

Leet code 1658 将x减到0的最小操作数

解题思路&#xff1a;滑动窗口 主要思想&#xff1a;正难逆简 题目需要左找一个数 右找一个数 我们不如直接找中间最长的一连串子数让这串子树和为 数组子树和减去X 找不到就返回 -1 滑动窗口双指针从左端出发&#xff0c;进行 进窗口 判断 出窗口 更新结果四个步骤 代码…

防火墙中的SNAT 与DNAT

SNAT&#xff1a;让内网机器可以访问外网服务器 DNAT:让外网机器可以访问内网服务器 SNAT的原理 源地址转换&#xff0c;根据指定条件修改数据包的源IP地址&#xff0c;通常被叫做源映射 数据包从内网发送到公网时&#xff0c;SNAT会把数据包的源IP由私网IP转换成公网IP 当响应…

【JetsonNano】onnxruntime-gpu 环境编译和安装,支持 Python 和 C++ 开发

1. 设备 2. 环境 sudo apt-get install protobuf-compiler libprotoc-devexport PATH/usr/local/cuda/bin:${PATH} export CUDA_PATH/usr/local/cuda export cuDNN_PATH/usr/lib/aarch64-linux-gnu export CMAKE_ARGS"-DONNX_CUSTOM_PROTOC_EXECUTABLE/usr/bin/protoc&qu…

OJ_点菜问题(背包问题)

题干 C实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<vector> using namespace std;int main() {int c, n;scanf("%d%d", &c, &n);int p[101];int v[101];for (int i 0; i < n; i){scanf("%d%d", &p[i],…

Android Studio实现内容丰富的安卓宠物用品管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 项目编号128 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.系统公告 3.宠物社区&#xff08;可发布宠物帖子&#xf…

47、C++/引用,函数重载,类相关学习20240312

一、自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show()。 代码&…

架构设计-复杂度来源:高性能

对性能孜孜不倦的追求是整个人类技术不断发展的根本驱动力。例如计算机&#xff0c;从电子管计算机到晶体管计算机再到集成电路计算机&#xff0c;运算性能从每秒几次提升到每秒几亿次。但伴随性能越来越高&#xff0c;相应的方法和系统复杂度也是越来越高。现代的计算机 CPU 集…

Html+threejs数字孪生三维场景实现

程序示例精选 Htmlthreejs数字孪生三维场景实现 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《Htmlthreejs数字孪生三维场景实现》编写代码&#xff0c;代码整洁&#xff0c;规则&#xf…

第十四届蓝桥杯省赛真题 Java 研究生 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 特殊日期试题 B: 与或异或试题 C: 棋盘试题 D: 子矩阵试题 E : \mathrm{E}: E: 互质数的个数试题 F: 小蓝的旅行计划试题 G: 奇怪的数试题 H: 太阳试题 I: 高塔试题 J \mathrm{J} J : 反异或 01 串 发现宝藏 前些天发现了一个巨牛的人…

helm部署hadoop

&#xff08;作者&#xff1a;陈玓玏&#xff09; 参考helm仓库的文档&#xff1a;https://artifacthub.io/packages/helm/apache-hadoop-helm/hadoop helm helm repo add pfisterer-hadoop https://pfisterer.github.io/apache-hadoop-helm/ helm install hadoop pfistere…

P1086 [NOIP2004 普及组] 花生采摘

题目描述 鲁宾逊先生有一只宠物猴&#xff0c;名叫多多。这天&#xff0c;他们两个正沿着乡间小路散步&#xff0c;突然发现路边的告示牌上贴着一张小小的纸条&#xff1a;“欢迎免费品尝我种的花生&#xff01;――熊字”。 鲁宾逊先生和多多都很开心&#xff0c;因为花生正…