如何在C#中实现OPC关于数据访问中间件

如何在C#中实现OPC 数据访问
说明:&&C#编程实现与西门子OPC通讯,西门子官方认证文件(C# programming and SIEMENS OPC communication)
文件列表:
如何在C#中实现OPC 数据访问.pdf
近期下载者:
相关文件:>> C#OPC客户端
C#OPC客户端
所属分类:
下载地址:
C#OPC.rar文件大小:643.29 kB
分享有礼! 》
请点击右侧的分享按钮,把本代码分享到各社交媒体。
通过您的分享链接访问Codeforge,每来2个新的IP,您将获得0.1 积分的奖励。
通过您的分享链接,每成功注册一个用户,该用户在Codeforge上所获得的每1个积分,您都将获得0.2 积分的分成奖励。
C# 通过OPC 类库,访问OPC SERVER 读取 变量,数据块内容
Sponsored links
源码文件列表
温馨提示: 点击源码文件名可预览文件内容哦 ^_^
如何在C#中实现OPC数据访问.pdf737.89 kB11-02-14 08:45
(提交有效评论获得积分)
评论内容不能少于15个字,不要超出160个字。
评价成功,多谢!
下载C#OPC.rar
CodeForge积分(原CF币)全新升级,功能更强大,使用更便捷,不仅可以用来下载海量源代码马上还可兑换精美小礼品了
您的积分不足,优惠套餐快速获取 30 积分
10积分 / ¥100
30积分 / ¥200原价 ¥300 元
100积分 / ¥500原价 ¥1000 元
订单支付完成后,积分将自动加入到您的账号。以下是优惠期的人民币价格,优惠期过后将恢复美元价格。
支付宝支付宝付款
微信钱包微信付款
更多付款方式:、
您本次下载所消耗的积分将转交上传作者。
同一源码,30天内重复下载,只扣除一次积分。
鲁ICP备号-3 runtime:Elapsed:51.460ms - init:0.1;find:0.6;t:1.0;tags:0.3;related:10.5;comment:0.2; 27.69
登录 CodeForge
还没有CodeForge账号?
Switch to the English version?
^_^"呃 ...
Sorry!这位大神很神秘,未开通博客呢,请浏览一下其他的吧菜鸟跪求 C# 开发OPC UA 客户端 指导,大神门行行好
菜鸟跪求 C# 开发OPC UA 客户端 指导,大神门行行好
来自: (呵呵)
如题,有UA Quickstart Applications和UA Sample Applications,想开发自己设计的界面的客户端,一直困难重重,求指导基于Visual C#的OPC客户端实现
> 基于Visual C#的OPC客户端实现
基于Visual C#的OPC客户端实现
摘 要:是连接数据源(服务器)和数据的使用者(应用程序)之间的软件接口标准。这里以C#为开发工具,按照OPC技术的规范标准,将OPC技术应用到虚拟仪器显示组件中。具体实现了OPC客户端数据访问服务器的过程,接口步骤及其读写数据的方法,并根据OPC服务器提供的数据,最终在虚拟仪器显示组件中生成了虚拟的正弦波、方波、锯齿波、三角波等。关键词:OPC;OPC接口;OPC服务器;C#本文引用地址:0 引 言 随着计算机技术和数字信号处理技术的发展,人们可以用计算机软件替代传统的硬件实现的一些功能,将计算机硬件和软件有机的融合为一体,这就是所谓的虚拟仪器。近年来,世界各国的虚拟仪器公司开发了不少基于LabVIEW,Matlab,VC++,VB等虚拟仪器开发平台软件,当硬件操作的设备驱动改变时,软件开发人员需要修改大量的驱动程序来连接此设备,因此使得虚拟仪器开发平台开发难度大、通用性差。为此,提出了基于OPC技术的虚拟仪器,它是由硬件供应商和软件开发商之间建立一套完整的“规则”,只要遵循这套规则,数据交互对两者来说都是透明的,硬件供应商无需考虑应用程序的多种需求和传输协议,软件开发商也无需了解硬件的实质和操作过程。l OPC技术 OPC(OLE Process Contro1)是OPC基金会组织倡导的工业控制和生产自动化领域中使用的硬件和软件的接口标准,以便有效地在应用和过程控制设备之间读写数据,具体的功能实现要由开发商根据需要自主的进行研究与开发。换句话说OPC规范是一套公共的软件标准,任何OPC开发人员所开发的OPC软件都要符合这个标准。 OPC技术的特点可概括为如下3个方面:开放性(Openness)、产业性(Productivity)和“即插即用”的互联性(Connectivity),因此可以说,“OPC=Openness+Productivity+Connectivity”,这也是对OPC优点最概括的描述。因此OPC在短时间内取得了飞速的发展。1.1 OPC服务器的组成 OPC标准采用C/S模式,OPC服务器负责向OPC客户端不断的提供数据。OPC服务器包括3类对象(Object):服务器对象(Server)、组对象(roup)和项对象(Item)。3类对象都包括一系列接口,关系如图1所示。 OPC服务器对象维护有关服务器信息,并作为OPC组对象的包容器,它提供了对数据源进行读/写和通信的接口方法,可以动态地创建或释放组对象。 OPC组对象由客户端定义和维护,它维护有关其自身的信息,提供包容OPC项对象的机制,从逻辑上实现对OPC项的管理。 OPC项对象包含在OPC组中,可由客户端定义和维护。项代表了与数据源的连接,所有的OPC项的操作都是通过包容此项的OPc组对象完成的。1.2 OPC的接口方式 OPC服务器通常支持两种类型的访问接口:自定义接口(The OPC Custom Interfaces)和自动化接口(The OPC Automation Interfaces),它们分别为不同的编程语言环境提供访问机制。 自定义接口是任何OPC服务器所必须实现的接口,它描述了OPC组件对象的接口和其实现的方法,适合C++语言设计,并可实现最佳运行性能的客户应用程序。 自动化接口是可选接口(Optional Interface),它提供了自动配置和存取过程控制数据的接口,方便了 Basic,Delphi,C#及其他可以使用自动化服务器应用程序接口的高级商业软件使用。自动化接口实际上是定制接口上的自动化封装,OPC规范通过提供一套标准的自动化接口包装器来实现这一功。1.3 OPC通信方式 OPC规范规定了两种通信方式:同步通信方式和异步通信方式。 同步通信时,OPC客户程序对OPC服务器进行读写操作时,OPC客户程序必须等到OPC服务器对应的操作全部完成以后才能返回,在此期间OPC客户程序一直处于等待状态。如果有大量数据进行操作或者有大量OPC客户程序对OPC服务器进行读写操作,必然造成OPC客户程序的阻塞现象。因此同步通信适用于OPC客户较少,数据量较小时的场合。 异步通信时,OPC客户程序对服务器进行读写操作时,OPC客户程序操作后立刻返回,不用等待OPC服务器的操作,可以进行其他操作。当0PC服务器完成操作后再通知OPC客户程序。因此,相对于同步通信和异步通信的效率更高,适用于多客户访问同一OPC服务器和大量数据的场合。
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一如何在C#中实现OPC数据访问 三亿文库
如何在C#中实现OPC数据访问
public virtual void OnReadComplete(System.Int32 dwTransid, //异步读完成触发 System.Int32 hGroup, System.Int32 hrMasterquality, System.Int32 hrMastererror, System.Int32 dwCount, int[] phClientItems, object[] pvValues, short[] pwQualities, OpcRcw.Da.FILETIME[] pftTimeStamps, int[] pErrors) public virtual void OnWriteComplete ( System.Int32 dwTransid , //异步写完成触发 System.Int32 hGroup , System.Int32 hrMastererr , System.Int32 dwCount , int[] pClienthandles , int[] pErrors )
public virtual void OnCancelComplete(System.Int32 dwTransid, System.Int32 hGroup) //取消特定操作触发 public virtual void OnDataChange(Int32 dwTransid, Int32 hGroup, //订阅方式下读触发
IA&DT Service & Support
Page 16-47
Int32 hrMasterquality, Int32 hrMastererror, Int32 dwCount, int[] phClientItems, object[] pvValues, short[] pwQualities, OpcRcw.Da.FILETIME[] pftTimeStamps, int[] pErrors)
问题 3:运行时,有时会弹出 Cross-thread operation not valid 错误,这是 C#中 对控件继承性的一种严格要求,在调试时会出现,可以做如下处理。 在 Form 的.ctor 中,InitealizeComponent 语句做如下处理:
public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = }
第六步,异步写数据
private void Btn_Write_Click(object sender, EventArgs e) { ?? object[] values = new object[4]; values[0] = Txt_W1.T values[1] = Txt_W2.T values[2] = \采用常数 values[3] = 1; //采用常数 IOPCAsyncIO2Obj.Write(4, ItemServerHandle, values, 3, out nCancelid, out pErrors); //异步写数据 ??
} 写完成处理(执行结果监视)
public virtual void OnWriteComplete ( System.Int32 dwTransid , System.Int32 hGroup , System.Int32 hrMastererr , System.Int32 dwCount , int[] pClienthandles , int[] pErrors ) { ?? ServerObj.GetErrorString( pErrors[0], LOCALE_ID, out strResult); Txt_WriteStatus1.Text = strR ?? }
第七步,订阅方式读数据
IA&DT Service & Support Page 17-47
OPC 服务器的 Group 组在组内有数据发生改变时,自动根据更新周期刷新相应的客户 端数据。工程应用中,大量数据的操作使用订阅方式更有优势。 订阅方式下,要考虑数据更新速度,及是否采用订阅方式读写。
private void CHK_Btn_CheckedChanged(object sender, EventArgs e) { ?? GCHandle hActive = GCHandle.Alloc(nActive, GCHandleType.Pinned); if (CHK_Btn.Checked != true) hActive.Target = 0; else hActive.Target = IOPCGroupStateMgtObj.SetState(pRequestedUpdateRate, out 1; ?? nRevUpdateRate, hActive.AddrOfPinnedObject(), pTimeBias, pDeadband, pLCID, hClientGroup); //为组设定特定信息 ?? } 通过IOPCDataCallback的虚函数OnDataChange实现 public virtual void OnDataChange(Int32 dwTransid, Int32 hGroup, Int32 hrMasterquality, Int32 hrMastererror, Int32 dwCount, int[] phClientItems, object[] pvValues, //值 short[] pwQualities, //质量码 OpcRcw.Da.FILETIME[] pftTimeStamps, //时间戳 int[] pErrors) { ?? if (phClientItems[nCount] == 1) //根据Item在客户端注册句柄查询 { Txt_R1_Value.Text = Convert.ToString(pvValues[nCount]); Txt_R1_Quality.Text = GetQuality(pwQualities[nCount]); DateTime dt = ToDateTime(pftTimeStamps[nCount]); Txt_R1_TimeStamp.Text = dt.ToString(); } ?? }
第八步,注销相应实例
private void Btn_Disconn_Click(object sender, EventArgs e) { ??
IA&DT Service & Support
Page 18-47
} 实例参考
参考第 8 节代码。 5、采用自动化接口实现过程 对于自动化接口,程序相应简单些。 建立项目:Automation_RW
测试中,对 db10.dbw0 及 db10.dbw2 读写操作,在 Form 窗口做如下设计: Control Button: Button: Button: Button: Button: Button: name Btn_Conn Btn_Read_S Btn_Read_A Btn_Write_S Btn_Write_A Btn_DisConn Text Conn Read_S Read_A Write_S Write_A disConn
IA&DT Service & Support
Page 19-47
TextBox: TextBox: TextBox: TextBox: TextBox: TextBox: TextBox: TextBox: TextBox:
Txt_R1_Value Txt_R1_Quality Txt_R1_TimeStamp Txt_R2_Value Txt_R2_Quality Txt_R2_TimeStamp Txt_W1 Txt_W2 Txt_ Txt_WriteStatus2
CheckBox: CHK_Btn
第一步,添加下列命名空间(首先在 COM 组件中添加相应组件)
using OPCSiemensDAA
第二步,定义 OPC 相关变量
OPCServer MyOpcS //定义OPCServer OPCGroup MyOpcG //定义组 OPCItem MyOpcItem1; //Item OPCItem MyOpcItem2; //值 long[] ServerHandle = new long[2]; //Item 的句柄
第三步,建立连接及对象
MyOpcServer = new OPCServer(); MyOpcServer.Connect(\\MyOpcGroup = MyOpcServer.OPCGroups.Add(\MyOpcItem1 = MyOpcGroup.OPCItems.AddItem(\connection_1]DB10,INT0\MyOpcItem2 = MyOpcGroup.OPCItems.AddItem(\connection_1]DB10,INT2\2); ServerHandle[0] = MyOpcItem1.ServerH ServerHandle[1] = MyOpcItem2.ServerH
IA&DT Service & Support
Page 20-47
第四步,同步读数据,
private void Btn_Read_S_Click(object sender, EventArgs e)//同步读数据 { ?? MyOpcItem1.Read(1,out ItemValues, out Qualities, out TimeStamps); //ItemValues,Qualities,TimeStamps分别是值,质量码及时间 //也可以通过调用SyncRead函数,参数可参考异步读函数 ?? }
第四步,同步写数据
private void Btn_Write_S_Click(object sender, EventArgs e) { ?? MyOpcItem1.Write(Txt_W1.Text); //也可以通过调用SyncWrite函数,参数可参考异步写函数 ?? }
第五步,异步事件定义, 在异步操作情况下,需要定义相应的异步事件
MyOpcGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(MyOpcGroup_DataChange); // //订阅方式下数据改变 iteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(MyOpcGroup_WriteComplete); //写完成事件 MyOpcGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(MyOpcGroup_ReadComplete); //读完成事件 MyOpcGroup.AsyncCancelComplete += new DIOPCGroupEvent_AsyncCancelCompleteEventHandler(MyOpcGroup_CancelComplete); //取消操作事件
在使用中注意,其事件函数要按照特定接口:
void MyOpcGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) void MyOpcGroup_WriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors) void MyOpcGroup_ReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Errors) void MyOpcGroup_CancelComplete(int CancelID)
第六步订阅方式读
void MyOpcGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { ?? //注意数据改变时,Item 数量要通过 NumItems 得到,也就是说只有数据改变时,才对一 遍,所以降低了服务器负担。要注意读语句写法。
IA&DT Service & Support
Page 21-47
第七步异步读
private void Btn_Read_A_Click(object sender, EventArgs e)//异步读事件 { int[] handle = new int[3] {ServerHandle[0], ServerHandle[1],0};//注意方式 Array MyServerHandles = (Array) A int cancelID; ?? MyOpcGroup.AsyncRead(2, ref MyServerHandles, out errors, READASYNC_ID, out cancelID); ?? } void MyOpcGroup_ReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Errors) { ?? //注意TransactionID的对应 ?? }
注意 array 在函数内部做参数时,数据下标是从 1 开始的,所以要考虑将第 0 位空出 来,n 个 Item,就要定义 n+1 列数组,添加一个 0,但在函数使用时,又是从左开始读的。 否则会报错。 第八步异步写
private void Btn_Write_A_Click(object sender, EventArgs e) { ?? MyOpcGroup.AsyncWrite(2, ref MyServerHandles, ref Myvalues, out errors, WRITEASYNC_ID, out cancelID); ?? } void MyOpcGroup_WriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors) { ?? }
同样要注意 Array 在函数内部做参数的传递。 第九步释放对象
private void Btn_Disconn_Click(object sender, EventArgs e) { ?? }
参考第 8 节代码。
IA&DT Service & Support
Page 22-47
6、OPCItem 的数据类型 在通过自定义接口访问时,
ItemArray[1].szAccessPath = \ItemArray[1].szItemID = \connection_1]DB10,Real4\地址,不同数据类型表示 ItemArray[1].bActive = 1;//是否激活 ItemArray[1].hClient = 2;//表示ID ItemArray[1].dwBlobSize = 0; ItemArray[1].pBlob = IntPtr.Z ItemArray[1].vtRequestedDataType = 5; ItemArray[2].szAccessPath = \ItemArray[2].szItemID = \connection_1]DB10,STRING26.10\地址,不同数据类型表 示方法不同 ItemArray[2].bActive = 1;//是否激活 ItemArray[2].hClient = 3;//表示ID ItemArray[2].dwBlobSize = 0; ItemArray[2].pBlob = IntPtr.Z ItemArray[2].vtRequestedDataType = 8;
在上面可以看到,vtRequestedDataType 代表了不同数据类型,在使用中需要注意的。 VbBoolean 11 7、小结 在实际应用中,根据实际要求,合理选择读写方式是很重要的。同时实例中是以 SimaticNet 的 OPCServer 为例,对于 WinCC 作为 OPCServer 同样适用,只需要将 \改为\。 同时需要注意的是,测试环境客户端需要安装 simaticNet。如果不安装,需要另行配 置,注册相应动态连接库。 8、代码 8.1 自动化接口
using using using using using using using using S System.Collections.G ponentM System.D System.D System.T System.Windows.F System.C
VbDecimal 14
VbDouble 5
Vbinteger 2
VbSingle 4
VbString 8
using OPCSiemensDAA//引用连接库 namespace Automation_RW
IA&DT Service & Support
Page 23-47
{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } OPCServer MyOpcS//OPCServer OPCGroup MyOpcG// OPCItem MyOpcItem1; OPCItem MyOpcItem2; int[] ServerHandle = new int[2];//服务器端注册句柄 const int READASYNC_ID=1;//异步读事务 const int WRITEASYNC_ID=2;//异步写事务
private void Btn_Conn_Click(object sender, EventArgs e)//建立连接 { try { MyOpcServer = new OPCServer(); MyOpcServer.Connect(\\MyOpcGroup.IsActive = MyOpcGroup.IsSubscribed =//是否异步,在采用异步读写,订阅等方式下都需要 为 MyOpcGroup.DeadBand = 0; MyOpcGroup.UpdateRate = 1000;//更新速率s MyOpcItem1 = MyOpcGroup.OPCItems.AddItem(\connection_1]DB10,INT0\1); MyOpcItem2 = MyOpcGroup.OPCItems.AddItem(\connection_1]DB10,INT2\2); ServerHandle[0] = MyOpcItem1.ServerH ServerHandle[1] = MyOpcItem2.ServerH MyOpcGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(MyOpcGroup_WriteComplete); MyOpcGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(MyOpcGroup_ReadComplete); MyOpcGroup.AsyncCancelComplete += new DIOPCGroupEvent_AsyncCancelCompleteEventHandler(MyOpcGroup_CancelComplete); MyOpcGroup.DataChange += DIOPCGroupEvent_DataChangeEventHandler(MyOpcGroup_DataChange); new } catch(System.Exception error) { MessageBox.Show(error.Message, \server\
IA&DT Service & Support
Page 24-47
private void Btn_Read_S_Click(object sender, EventArgs e)//同步读数据 { object ItemV object Q object TimeS try { MyOpcItem1.Read(1,out ItemValues, out Qualities, out TimeStamps); Txt_R1_Value.Text = String.Format(\ItemValues); // Quality Txt_R1_Quality.Text = String.Format(\Timestamp Txt_R1_TimeStamp.Text = String.Format(\TimeStamps); } catch (System.Exception error) { MessageBox.Show(error.Message, \- 同步读\MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void Btn_Write_S_Click(object sender, EventArgs e)//同步写数据 { try { MyOpcItem1.Write(Txt_W1.Text); } catch (System.Exception error) { MessageBox.Show(error.Message, \- 同步写\MessageBoxButtons.OK, MessageBoxIcon.Error); } }
void MyOpcGroup_CancelComplete(int CancelID) { //增加相应代码 } private void Btn_Read_A_Click(object sender, EventArgs e)//异步读事件 { int[] handle = new int[3] {ServerHandle[0], ServerHandle[1],0};//注意写的方式 Array MyServerHandles = (Array) A int cancelID; try { MyOpcGroup.AsyncRead(2, ref MyServerHandles, out errors, READASYNC_ID, out cancelID); }
IA&DT Service & Support
Page 25-47
catch (System.Exception error) { MessageBox.Show(error.Message, \异步读\MessageBoxButtons.OK, MessageBoxIcon.Error); } } //读完成事件 void MyOpcGroup_ReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Errors) { try { if (TransactionID == READASYNC_ID) { if(Convert.ToInt32(ClientHandles.GetValue(1))==1) { if (Convert.ToInt32(Errors.GetValue(1))==0) { Txt_R2_Value.Text = ItemValues.GetValue(1).ToString(); Qualities.GetValue(1).ToString(); TimeStamps.GetValue(1).ToString(); } } Txt_R2_Quality.Text Txt_R2_TimeStamp.Text = =
} //增加其余的代码 } catch (System.Exception error) { MessageBox.Show(error.Message, \- 异步读\MessageBoxButtons.OK, MessageBoxIcon.Error); } } //订阅方式 void MyOpcGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { try { for (int i = 0; i < NumI i++) { for (int j = 1;
联系客服:cand57</

我要回帖

更多关于 数据访问层设计与实现 的文章

 

随机推荐