【转】(C#)OPC客户端源码
本例下载/Files/badnewfish/OPC测试通过.rar
转载申明
申明:本文为转载,如需转载本文,请获取原文作者大尾巴狼啊的同意,谢谢合作!
转自:大尾巴狼啊
原文出处:http://www.cnblogs.com/xiaosacao/archive/2009/01/13/1374895.html
前几天我就发布过这篇文章,可惜的是,发布后代码有的却看不到,后来我就删了,至今不明白什么原因- -!
关于C++、VB来开发OPC客户端的资料网上有很多,但C#的至今没发现有多少。
由于近期项目的需要,就开发了OPC客户端的一个模块。在我想来,程序员挺累的,原因我很累。所以我想大家也很累~~~嘿嘿。
特别是刚接手OPC客户端开发的前几天,天天盯住显示器,百度、GOOGLE不停的搜索。每天早上醒来,眼睛都瑟瑟的。
从事3年以上软件开发的朋友们,估计都会腰酸背痛吧!反正我是这样的。
不说那么多废话了,贴上源码,让需要的同行看看吧,代码的质量并不高,就当做抛砖引玉吧!
1、枚举本地服务器
2、获取服务器信息
3、列出了服务器上Tag
4、可以设置组的属性
5、读\写功能
6、可进行远程连接(DCOM需配置)
先看图:

引用类库:

OPC服务器:

开发工具:

当前环境:

源码:
Code ///摘要 ///程式使用C#.NET 2005 编写 ///引用类库OPCDAAuto.dll ///OPCServer采用KEPWare ///在windows xp sp2、sp3、windows 2003上测试通过 ///完成于:2008年12月31日 ///测试于:2009年01月05日 /// ///作者:潇洒草 ///Email:zhkai868@163.com ///QQ:44649029 /// ///如分发,请保留此摘要。 ///鄙视那些拿代码当宝贝的人,鄙视那些你不拿源码换就不稀罕你的人,鄙视那些自私的人。 ///别人看到你的代码,你能死啊?对你有多大威胁啊?强烈鄙视~~~ ///如果你是这样的人,赶紧关了。。偶不欢迎。。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.Collections; using OPCAutomation;
namespace OPC测试通过 { public partial class MainFrom : Form { public MainFrom() { InitializeComponent(); }
#region 私有变量 /// <summary> /// OPCServer Object /// </summary> OPCServer KepServer; /// <summary> /// OPCGroups Object /// </summary> OPCGroups KepGroups; /// <summary> /// OPCGroup Object /// </summary> OPCGroup KepGroup; /// <summary> /// OPCItems Object /// </summary> OPCItems KepItems; /// <summary> /// OPCItem Object /// </summary> OPCItem KepItem; /// <summary> /// 主机IP /// </summary> string strHostIP = ""; /// <summary> /// 主机名称 /// </summary> string strHostName = ""; /// <summary> /// 连接状态 /// </summary> bool opc_connected = false; /// <summary> /// 客户端句柄 /// </summary> int itmHandleClient = 0; /// <summary> /// 服务端句柄 /// </summary> int itmHandleServer = 0; #endregion
#region 方法 /// <summary> /// 枚举本地OPC服务器 /// </summary> private void GetLocalServer() { //获取本地计算机IP,计算机名称 IPHostEntry IPHost = Dns.Resolve(Environment.MachineName); if (IPHost.AddressList.Length > 0) { strHostIP = IPHost.AddressList[0].ToString(); } else { return; } //通过IP来获取计算机名称,可用在局域网内 IPHostEntry ipHostEntry = Dns.GetHostByAddress(strHostIP); strHostName=ipHostEntry.HostName.ToString();
//获取本地计算机上的OPCServerName try { KepServer = new OPCServer(); object serverList = KepServer.GetOPCServers(strHostName);
foreach (string turn in (Array)serverList) { cmbServerName.Items.Add(turn); }
cmbServerName.SelectedIndex = 0; btnConnServer.Enabled = true; } catch(Exception err) { MessageBox.Show("枚举本地OPC服务器出错:"+err.Message,"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Warning); }
} /// <summary> /// 创建组 /// </summary> private bool CreateGroup() { try { KepGroups = KepServer.OPCGroups; KepGroup = KepGroups.Add("OPCDOTNETGROUP"); SetGroupProperty(); KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange); KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete); KepItems = KepGroup.OPCItems; } catch (Exception err) { MessageBox.Show("创建组出现错误:"+err.Message,"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Warning); return false; } return true; } /// <summary> /// 设置组属性 /// </summary> private void SetGroupProperty() { KepServer.OPCGroups.DefaultGroupIsActive =Convert.ToBoolean(txtGroupIsActive.Text); KepServer.OPCGroups.DefaultGroupDeadband = Convert.ToInt32(txtGroupDeadband.Text); KepGroup.UpdateRate = Convert.ToInt32(txtUpdateRate.Text); KepGroup.IsActive = Convert.ToBoolean(txtIsActive.Text); KepGroup.IsSubscribed =Convert.ToBoolean(txtIsSubscribed.Text); } /// <summary> /// 列出OPC服务器中所有节点 /// </summary> /// <param name="oPCBrowser"></param> private void RecurBrowse(OPCBrowser oPCBrowser) { //展开分支 oPCBrowser.ShowBranches(); //展开叶子 oPCBrowser.ShowLeafs(true); foreach (object turn in oPCBrowser) { listBox1.Items.Add(turn.ToString()); } } /// <summary> /// 获取服务器信息,并显示在窗体状态栏上 /// </summary> private void GetServerInfo() { tsslServerStartTime.Text ="开始时间:"+ KepServer.StartTime.ToString()+" "; tsslversion.Text ="版本:"+ KepServer.MajorVersion.ToString() + "." + KepServer.MinorVersion.ToString()+"."+KepServer.BuildNumber.ToString(); } /// <summary> /// 连接OPC服务器 /// </summary> /// <param name="remoteServerIP">OPCServerIP</param> /// <param name="remoteServerName">OPCServer名称</param> private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName) { try { KepServer.Connect(remoteServerName, remoteServerIP);
if (KepServer.ServerState == (int)OPCServerState.OPCRunning) { tsslServerState.Text = "已连接到-" + KepServer.ServerName + " "; } else { //这里你可以根据返回的状态来自定义显示信息,请查看自动化接口API文档 tsslServerState.Text = "状态:" + KepServer.ServerState.ToString() + " "; } } catch (Exception err) { MessageBox.Show("连接远程服务器出现错误:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } return true; } #endregion
#region 事件 /// <summary> /// 写入TAG值时执行的事件 /// </summary> /// <param name="TransactionID"></param> /// <param name="NumItems"></param> /// <param name="ClientHandles"></param> /// <param name="Errors"></param> void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors) { lblState.Text = ""; for (int i = 1; i <= NumItems; i++) { lblState.Text += "Tran:" + TransactionID.ToString() + " CH:" + ClientHandles.GetValue(i).ToString() + " Error:" + Errors.GetValue(i).ToString(); } } /// <summary> /// 每当项数据有变化时执行的事件 /// </summary> /// <param name="TransactionID">处理ID</param> /// <param name="NumItems">项个数</param> /// <param name="ClientHandles">项客户端句柄</param> /// <param name="ItemValues">TAG值</param> /// <param name="Qualities">品质</param> /// <param name="TimeStamps">时间戳</param> void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { //为了测试,所以加了控制台的输出,来查看事物ID号 //Console.WriteLine("********"+TransactionID.ToString()+"*********"); for (int i = 1; i <= NumItems; i++) { this.txtTagValue.Text = ItemValues.GetValue(i).ToString(); this.txtQualities.Text = Qualities.GetValue(i).ToString(); this.txtTimeStamps.Text = TimeStamps.GetValue(i).ToString(); } } /// <summary> /// 选择列表项时处理的事情 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { try { if (itmHandleClient != 0) { this.txtTagValue.Text = ""; this.txtQualities.Text =""; this.txtTimeStamps.Text = "";
Array Errors; OPCItem bItem = KepItems.GetOPCItem(itmHandleServer); //注:OPC中以1为数组的基数 int[] temp = new int[2] { 0, bItem.ServerHandle }; Array serverHandle = (Array)temp; //移除上一次选择的项 KepItems.Remove(KepItems.Count, ref serverHandle, out Errors); } itmHandleClient = 1234; KepItem = KepItems.AddItem(listBox1.SelectedItem.ToString(), itmHandleClient); itmHandleServer = KepItem.ServerHandle; } catch(Exception err) { //没有任何权限的项,都是OPC服务器保留的系统项,此处可不做处理。 itmHandleClient = 0; txtTagValue.Text = "Error ox"; txtQualities.Text = "Error ox"; txtTimeStamps.Text = "Error ox"; MessageBox.Show("此项为系统保留项:"+err.Message,"提示信息"); } } /// <summary> /// 载入窗体时处理的事情 /// </summary> private void MainFrom_Load(object sender, EventArgs e) { GetLocalServer(); } /// <summary> /// 关闭窗体时处理的事情 /// </summary> private void MainFrom_FormClosing(object sender, FormClosingEventArgs e) { if (!opc_connected) { return; }
if (KepGroup != null) { KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange); }
if (KepServer != null) { KepServer.Disconnect(); KepServer = null; }
opc_connected = false; } /// <summary> /// 【按钮】设置 /// </summary> private void btnSetGroupPro_Click(object sender, EventArgs e) { SetGroupProperty(); } /// <summary> /// 【按钮】连接OPC服务器 /// </summary> private void btnConnLocalServer_Click(object sender, EventArgs e) { try { if (!ConnectRemoteServer(txtRemoteServerIP.Text,cmbServerName.Text)) { return; }
btnSetGroupPro.Enabled = true;
opc_connected = true;
GetServerInfo();
RecurBrowse(KepServer.CreateBrowser());
if (!CreateGroup()) { return; } } catch (Exception err) { MessageBox.Show("初始化出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } /// <summary> /// 【按钮】写入 /// </summary> private void btnWrite_Click(object sender, EventArgs e) { OPCItem bItem = KepItems.GetOPCItem(itmHandleServer); int[] temp = new int[2] { 0, bItem.ServerHandle }; Array serverHandles=(Array)temp; object[] valueTemp = new object[2] {"",txtWriteTagValue.Text }; Array values=(Array)valueTemp; Array Errors; int cancelID; KepGroup.AsyncWrite(1,ref serverHandles,ref values,out Errors, 2009,out cancelID); //KepItem.Write(txtWriteTagValue.Text);//这句也可以写入,但并不触发写入事件 GC.Collect(); } #endregion } }
自动化接口API文档:

关于DCOM的配置:

update:
1、本文中是在2009年元月写的,可能有很多过时之处,现在最新(2014年)的OPC官网已经有关于C#调用的例子:http://www.opcfoundation.org/default.aspx/classicdownloads.asp?MID=Developers
2、客户端连接OPC服务器注意事项:
a、本例采用的OPCDAAuto.dll版本是2.2.5.20。 b、需要使用“regsvr32 /s OPCDAAuto.dll”命令在客户端计算机上注册这个程序集。 c、首先保证客户机和服务器的网络是联通的。
【转】(C#)OPC客户端源码的更多相关文章
- swift实现饭否应用客户端源码
swift 版 iOS 饭否客户端 源码下载:http://code.662p.com/view/13318.html 饭否是中国大陆地区第一家提供微博服务的网站,被称为中国版Twitter.用户可通 ...
- android版高仿淘宝客户端源码V2.3
android版高仿淘宝客户端源码V2.3,这个版本我已经更新到2.3了,源码也上传到源码天堂那里了,大家可以看一下吧,该应用实现了我们常用的购物功能了,也就是在手机上进行网购的流程的,如查看产品(浏 ...
- C#中国象棋+游戏大厅 服务器 + 客户端源码
来源:www.ajerp.com/bbs C#中国象棋+游戏大厅 服务器 + 客户端源码 源码开源 C#版中国象棋(附游戏大厅) 基于前人大虾的修改版 主要用委托实现 服务器支持在线人数,大厅桌数的设 ...
- FileZilla客户端源码解析
FileZilla客户端源码解析 FTP是TCP/IP协议组的协议,有指令通路和数据通路两条通道.一般来说,FTP标准命令TCP端口号是21,Port方式数据传输端口是20. FileZilla作为p ...
- vs2008编译FileZilla客户端源码
vs2008编译FileZilla客户端源码 下载FileZilla客户端源码,下载地址https://download.filezilla-project.org/. FileZilla客户端解决方 ...
- Netty5客户端源码解析
Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...
- MQTT再学习 -- MQTT 客户端源码分析
MQTT 源码分析,搜索了一下发现网络上讲的很少,多是逍遥子的那几篇. 参看:逍遥子_mosquitto源码分析系列 参看:MQTT libmosquitto源码分析 参看:Mosquitto学习笔记 ...
- Zookeeper 源码(三)Zookeeper 客户端源码
Zookeeper 源码(三)Zookeeper 客户端源码 Zookeeper 客户端主要有以下几个重要的组件.客户端会话创建可以分为三个阶段:一是初始化阶段.二是会话创建阶段.三是响应处理阶段. ...
- MQTT 客户端源码分析
参看:逍遥子_mosquitto源码分析系列 参看:MQTT libmosquitto源码分析 参看:Mosquitto学习笔记 一.目录结构 首先我们还是来看一下 mosquitto-1.4.14 ...
随机推荐
- 数据结构与算法之排序(4)希尔排序 ——in dart
研究了网上大部分的希尔排序代码,发现大部分都是互相抄的——因为网上甚至某些书上的实现大部分都是错的.希尔排序是插入排序的升级版,通过引入间隔,然后分组进行插入排序.再逐步缩小间隔,直至间隔为1时,做全 ...
- 《Java 程序设计》课堂实践项目-Arrays和String单元测试
<Java 程序设计>课堂实践项目-Arrays和String单元测试 课后学习总结 目录 改变 Arrays和String单元测试实验要求 课堂实践成果 课后思考 改变 修改了博客整体布 ...
- JavaWeb总结(五)
使用Servlet接受服务器请求信息 HTTP请求示例 HttpServletRequest对象主要用于获取由客户端发送过来的请求头.参数.文件.数据等.Servlet存在的主要目的就是处理请求.Se ...
- v$pwfile_user表
SQL> select * from v$pwfile_users;select * from v$pwfile_users; USERNAME SYSDB SYSOP SYSAS------- ...
- Git 解决添加到.gitignore的忽略项不生效的问题
今天又在.gitignore添加了一些忽略项,但是后来发现一些东西命名配置了忽略项却还是没起作用,so,分析原因,可能是在我添加忽略项之前,因为这些文件就早已经被提交了,所有他们已经在版本控制中,导致 ...
- 牛客练习赛31 D 最小相似度
最小相似度 链接 分析: 转化为求1的个数,这样两个串不同的位置的个数就是1的个数.那么对于一个二进制串x,它的贡献就是max{x与s[i]异或后0的个数}=>max{m-x与s[i]异或后1的 ...
- JAVA中使用RSA通过秘钥文件对字符串进行加密解密
技术交流群: 233513714 //字符串进行加密算法的名称 public static final String ALGORITHM = "RSA"; //字符串进行加密填充的 ...
- docker部署jenkins环境
首先获取jenkins的镜像: docker pull jenkins 设置jenkins_home映射: sudo mkidr -p /jenkins_home /jenkins_home 启动容器 ...
- C# 代码备份数据库 ,不需要 其他 DLL
protected void Button1_Click(object sender, EventArgs e) { /// ///备份方法 /// ...
- Jmeter+ant+jenkins接口自动化测试 平台搭建(二)
一.依赖文件配置 1.在ant目录C:\apache-ant-1.10.5下新建一个demo文件夹,并将jmeter测试脚本放在该文件夹中 2.将\apache-jmeter-3.3\extras下面 ...