OPC客户端编程汇编

合集下载

手把手教您用VB编一个OPC客户端程序33页PPT

手把手教您用VB编一个OPC客户端程序33页PPT
手把手教您用VB编一个OPC客户端程

21、没有人陪你走一辈子,所以你要 适应孤 独,没 有人会 帮你一 辈子, 所以你 要奋斗 一生。 22、当眼泪流尽的时候,留下的应该 是坚强 。 23、要改变命运,首先改变自己。
24、勇气很有理由被当作人类德性之 首,因 为这种 德性保 证了所 有其余 的德性 。--温 斯顿. 丘吉尔 。 25、梯子的梯阶从来不是用来搁脚的 ,它只 是让人 们的脚 放上一 段时间 ,以便 让别一 只脚能不会再掉进坑里。——黑格尔 32、希望的灯一旦熄灭,生活刹那间变成了一片黑暗。——普列姆昌德 33、希望是人生的乳母。——科策布 34、形成天才的决定因素应该是勤奋。——郭沫若 35、学到很多东西的诀窍,就是一下子不要学很多。——洛克

OPC实验指导书

OPC实验指导书

实验名称OPC客户端的编程一、实验目的:通过实际操作进一步了解OPC的各种概念,掌握OPC客户端的编写方法。

并对微软的DCOM 有一定的了解,要求通过合适的DCOM配置,使客户端能够读取网络上服务器中的数据。

二、实验内容:1)利用VB语言编写出一个简单的OPC客户端程序,要求这个客户端能够读取服务器中的数据,并显示出来。

2)配置DCOM,使客户端能够能过DCOM读取另一台服务器上的数据。

三、实验步骤:(1)建立一个Visual Basic工程1)启动Visual Basic,新建一个Visual Basic工程。

选择[Standard EXE]作为新建工程的类型。

图3-1 Visual Basic 工程的建立2)设置OPC包装DLL因为在新建的Visual Basic工程OPC包装DLL还没有被注册,必须用下述方法对OPC包装DLL 进行注册。

设置方法:1.从Visual Basic菜单里选择[Project]-[References]。

2.在[Available References]表示中,选择对应OPC包装DLL的文件名。

这里我们选择[OPCAutomation 2.0]。

图3-2 引用的设置(2)建立一个OPC对象在Visual Basic里,是以对象的单位对OPC服务器进行访问。

OPC自动化接口是由以下四种对象所定义。

OPC服务器OPC组(OPC组集合)OPC标签(OPC标签集合)OPC浏览器这里只说明OPC服务器,OPC组以及OPC标签对象的使用方法。

具体的来说,先连接一个特定的OPC服务器,然后建立OPC组,最后添加OPC标签。

1)变量声明参考图3-3所示的示范代码,先对OPC对象变量进行声明。

变量的数据类型应该指定为对象型。

这些对象变量最好在窗体代码的(General)部分声明。

因为在(General)部分声明的变量,可以在窗体的任何方法的代码内引用。

图3-3 OPC对象变量的声明有关定义OPC对象的声明及其说明列于表3-1表3-1 OPC对象变量的声明2)连接OPC服务器和建立OPC组下面说明如何连接OPC服务器和建立OPC组。

汇编指令之OpCode快速入门

汇编指令之OpCode快速入门

汇编指令之OpCode快速入门:最近一直被一些初学者问及有关于汇编指令的长度问题,因此为此专门撰写本文,以求为不知OpCode为何物,或者正为汇编长短不一的指令而烦恼的朋友一个最为快速的指引。

其实,OpCode并不复杂,在本文中我不打算细致入微的告诉大家OpCode的原理,不会为大家带来一大堆有关于什么是定长指令、什么是变长指令的理论知识,更不会带着各位读者玩OpCode Hacking,我只会告诉你“怎么了”、“为什么”以及“如何解决”。

1、我的汇编指令怎么了?哦,天啊!怎么我今天突然发现汇编指令竟然是长短不一的!你还没发现吗?那么请过目:1E831880000CALL00430B862E917FEFFFF JMP0042817138B442404MOV EAX,DWORD PTR SS:[ESP+4]485C0TEST EAX,EAX556PUSH ESI68BF1MOV ESI,ECX我们可以看见“CALL00430B86”这条汇编指令竟然占用了5个字节,而“PUSH ESI”则只占用了1个字节,汇编指令的脾气犹如一只滑头的猴子一样让你摸不到头脑,它很明显的告诉了你“嘿!兄弟,你别想搞懂我!”你也许会感到很郁闷,但是我并不这么想,因为如果我要想自己搞一个反汇编引擎,或者是我要在我的壳里加上代码混淆功能……嗯,算了,就算是我想娱乐一下搞搞免杀吧,那么我终归是要搞懂它的,为什么?因为如果搞懂它的话,那么我就没办法做到这些!很明显我们的汇编指令继承了Intel工程师的狡猾本质,为了尽可能的减少体积,所以它们的体积被设计的不尽相同。

哇哦!很多读者此时似乎已经想明白是怎么回事了,肯定是不同的指令对应的字节数不一样,恩……这样只要我们搞到一张表就可以了!不是吗?一张可以描述每个指令所用二进制码的表格,然后我们就万事大吉了。

但是很不幸,我在初次接触OpCode时也想出了这个“超级点子”,但是很可惜我的“超级点子”与各位读者的一样,并没有为我解决任何问题,请过目:7B801000000MOV EAX,188BC3MOV EAX,EBX98BC7MOV EAX,EDI看到了吗,一样的指令,一样的目的操作数,得到的确是完全不同的机器码……2、这是为什么?嗯,我想这个问题是很明显的,源操作数如果是一个寄存器的话,那么能有几种可能呢?按照规则来讲貌似只有不超过50种可能,那么如果被操作数是一个数值呢?你想想,32位能表示多少数,将其乘以2就是最终的可能性了,这么多的可能性一定不是区区两个16位数就能表示过来的。

[信息与通信]手把手教您用VB编一个OPC客户端程序

[信息与通信]手把手教您用VB编一个OPC客户端程序

OPC
Agenda
OPC - Review of the Basics OPC - Terminology OPC & VB 101 - Automation Wrapper & Object Model Building Your VB Client - Read data - 7 easy steps with code from start to finish Housekeeping Handles Handles Everywhere - how the server and client correlate the data each is managing in your program Writing Data Future ideas to consider New developments since original presentation in 10/99 Resources for future learning
Copyright Software Toolbox, 1999,2000,2001 All Rights Reserved Worldwide. Software Toolbox is a registered trademark of Software Toolbox, Inc.
VB
OPC Your VB Program with the Automation Wrapper object included in it
• OPC Server - a piece of software supporting the OPC specification - an OPC Data Access Server is a driver that handles connectivity to PLCs or other automation hardware • OPC Item - A single tag or data point managed by the OPC server - i.e. one data point in a PLC • OPC Group - a user defined grouping of OPC items. Created by the OPC client as a way of organizing data items around logical process areas or equipment. • Collection - a grouping of objects of the same data type for example, each OPC server has an OPC items collection containing one software object for each OPC item.

用VB编写OPC

用VB编写OPC

winccopc:用VB编写OPC客户端访问WINCC-vb教程疯狂代码 / ĵ:http://VisualBasic/Article15470.html用VB编写OPC客户端访问WINCCOPC是个工业标准它是由些世界上著名自动化系统和硬件、软件Software公司和Microsoft(微软)紧密合作而建立〔O代表OLE(对象链接和嵌入)P (process过程)C (control控制)OLE已从面向对象重新定义为基于对象并更名为Active X〕WinCC是西门子公司在自动化领域采用最先进技术和微软公司在共同开发居于世界领先地位工控软件SoftwareWinCC即WINDOWS CONTROL CENTER(视窗控制中心)WinCC是个功能强大全面开放监控系统既可以用来完成小规模简单过程监控应用也可以用来完成复杂应用在任何情况下WinCC都可以生成漂亮而便捷人机对话接口使操作员能够清晰地管理和优化生产过程它集成OPC(OLE for process control)服务器使得过程数据可由其它应用(OPC客户机)访问WinCC在安装时提供了OPC客户端Control控件: Siemens OPC DAAutomation 2.0( SOPCDAAuto.dll),这个Control控件就是我们在VB中要用到Control控件我们也可以使用通用OPC客户端Control控件: OPC Automation 2.0.在WINCC帮助中有Siemens OPC DAAutomation 2.0使用简略帮助但说得不很详细我在使用中碰到不少问题现并写出来和大家共享、OPC连接 先在“引用”将近 Siemens OPC DAAutomation 2.0加入然后开始定义全局变量在本中我使用了两个OPC组进行OPC访问所以定义了全局变量我们要首先定义OPC服务类型和计算机结点名定义OPC组和OPC标签组并定义OPC标签和值数注意值定要设为Variant´OPC处理:只对WINCCConst ServerName = \"OPCServer.WinCC\" ‘OPC类型Const NodeName = \"GUK\" ‘结点名即计算机名‘Dim NodeName As StringDim WithEvents MyOPCServer As OPCServer ‘OPC服务Dim MyOPCGroupColl As OPCGroups ‘Dim WithEvents MyOPCGroupOut As OPCGroup ‘OPC组本用两个组进行OPC连接Dim WithEvents MyOPCGroupIn As OPCGroupDim MyOPCItemCollIn As OPCItems ‘OPC标签组Dim MyOPCItemCollOut As OPCItemsDim ServerHandlesIn As Long ‘句柄Dim ServerHandlesOut As LongDim ErrorsIn As Long ‘句柄Dim ErrorsOut As LongDim WatchDataReadItem(100) As String ´记录OPC标签Dim WatchDataReadValue(100) As Variant ´存放OPC值Dim WatchDataWriteItem(100) As String ´记录OPC标签Dim WatchDataWriteValue(100) As Variant ´存放OPC值在定义所有变量后我们就要进行OPC连接了要进行OPC连接的前,先要配置要访问OPC标签名我们WatchDataReadItem、WatchDataWriteItem中加入相应标签名注意:这两个必须由1开始不能由0开始配置好标签后就要进行OPC连接了如下面子:1、 ClientHandles1先配置名柄索引这将在读取OPC标签值时可要用到2、 生成OPC对象3、 进行OPC标签连接至此:OPC连接就成功了我们可以对OPC进行读和写操作了´--------------------------------------------------------------------- ´ Sub StartClient´ 目:连接至OPC_server创建组和添加条目´--------------------------------------------------------------------- Private Sub StartClientDim ItemNum As IntegerDim TarnscationID As LongDim CanceID As LongDim ClientHandles1(100) As LongDim ii As IntegerOn Error GoTo HANDLEeRRORFor ii = 0 To 100ClientHandles1(ii) = ii 先配置名柄索引这将在读取OPC标签值时可要用到 Next iiTarnscationID = 1‘ NodeName = xProfile.GetValue(\"SYSTEM\", \"NodeName\")‘生成OPC对象Set MyOPCServer = New OPCServerMyOPCServer.Connect ServerName, NodeNameSet MyOPCGroupColl = MyOPCServer.OPCGroupsMyOPCGroupColl.DefaultGroupIsActive = TrueSet MyOPCGroupIn = MyOPCGroupColl.Add(\"MYGROUPIN\")Set MyOPCGroupOut = MyOPCGroupColl.Add(\"MYGROUPOUT\") Set MyOPCItemCollIn = MyOPCGroupIn.OPCItemsSet MyOPCItemCollOut = MyOPCGroupOut.OPCItems‘进行OPC标签连接If WriteItemIdex > 0 ThenMyOPCItemCollOut.AddItems WriteItemIdex, WatchDataWriteItem, ClientHandles1, ServerHandlesOut, ErrorsOut ´化OCP连接MyOPCGroupOut.IsSubscribed = TrueEnd IfIf ReadItemIdex > 0 ThenMyOPCItemCollIn.AddItems ReadItemIdex, WatchDataReadItem, ClientHandles1, ServerHandlesIn, ErrorsIn ´化OCP连接MyOPCGroupIn.IsSubscribed = TrueEnd IfExit SubHANDLEeRROR:needOPCRestart = TruexLog1.log \"OPCl连接发生\"End Sub2、OPC标签读写对OPC标签读可以通过MyOPCGroupIn组和MyOPCGroupOutDataChange事件来读取该事件有多个参数:其中NumItems是指标签改变值个数ClientHandles是改变值标签索引ItemValues为改变值数据具体意思是ClientHandles(1)值是其对应标签索引其所指OPC标签值在ItemValues(1)中般来说刚连接上时该事件会把全部所要求访问OPC标签值全部读取过来(顺序不要通过ClientHandles索引)此后只有数据发生变化时才会触发该事件也只会传输发生了变化数据没有变化数据不会出现在本事件ItemValues中Private Sub MyOPCGroupOut_DataChange(ByVal TransactionID As Long, ByVal NumItems As Long, ClientHandles As Long, ItemValues As Variant, Qualities As Long, TimeStamps As Date)´产生要通知下级数据变化根椐不再Control控件有区别处理For ii = 1 To NumItemsWatchDataWriteValue(ClientHandles(ii) - 1) = ItemValues(ii) ´对改变值读入本Next iiEnd Sub对OPC写可以有同步和异步的分对于大量数据传输异步是更佳选择但对少量数据传输同步表现得更好要进行数据传输先要将值数据进行赋值注意:值数据要由0开始也就是说值和标签数据不是、对应值要比标签前位这点在WINCC介绍说明中没有但在我实际使用中直要这样不然数据就产生错位看下面这是个拔号完毕后返回数据进行OPC传递包含解包过程Private Sub showSuccess(msg As String)Dim location As StringDim nowTime As StringDim logStr As StringDim Value As StringDim ii, temp As IntegerDim isPack As BooleanDim sHead, sDelimited, sTail As Stringlocation = xProfile.GetValue(WatchPo(nowRunID), \"LOCATION\")nowTime = NowlogStr = \"拔\" & location & \"取数成功\" & msgxLog1.log logStrlogStr = \" \" & msgxLog2.log logStr ´记录数据´数据上传´如果有包结构,则显示包结构,isPack = xProfile.GetValue(WatchPo(nowRunID), \"ISRECHEAD\")If WatchPoRBegin(nowRunID) < 0 Then Exit SubIf isPack ThensHead = xProfile.GetValue(WatchPo(nowRunID), \"RECHEAD\")sDelimited = xProfile.GetValue(WatchPo(nowRunID), \"RECDELIMITER\") sTail = xProfile.GetValue(WatchPo(nowRunID), \"RECEND\")Value = Split(msg, sDelimited)For ii = 0 To UBound(Value) - 1temp = WatchPoRBegin(nowRunID) + iiIf temp > WatchPoREnd(nowRunID) Then Exit ForWatchDataReadValue(temp - 1) = Value(ii + 1) ´VALUE要从0开始比ITEM少1,所以减 有包头,占去位,向后延Next iiElseWatchDataReadValue(WatchPoREnd(nowRunID) - 1) = msgEnd IfMyOPCGroupIn.SyncWrite ReadItemIdex, ServerHandlesIn, WatchDataReadValue, ErrorsIn ´数据上传 ´记录上次成功执行时间xProfile.SetValue WatchPo(nowRunID), \"LASTTIME\", nowTimeEnd Sub3、OPC连接断开OPC客户端连接后要占用服务器资源所以如果不需要使用OPC时必须进行OPC连接断开断开相当简单释放资源即可如下Sub StopClient_disibledevent=>´----------- 释放组和服务器对象MyOPCGroupColl.RemoveAll´----------- 和服务器断开连接并且清除 MyOPCServer.DisconnectSet MyOPCItemCollIn = NothingSet MyOPCItemCollOut = NothingSet MyOPCGroupIn = NothingSet MyOPCGroupOut = NothingSet MyOPCGroupColl = NothingSet MyOPCServer = NothingEnd Sub但在实际使用中发现频繁连接和断开将使服务器资源被大量消耗最终让服务器出错所以尽量减少无谓OPC连接和断开结语: OPC使用是作为个DCOM在使用所以OPC客户端可以网络上任计算机运行但你必须配置DCOM访问权限如果你不想费神把服务器和客户端都用相同用户名和密码登录就成了如果想配置DCOM请参看DCOM配置参考资料:WinCC在线帮助作者介绍:顾恺高级员湖南大学毕业曾从事过LINUX内核研究从事过企业信息化平台开发当前从事SCADA开发主要将各种区别类型远程设备通过同手段进行数据采集并集成到企业信息化平台中去喜欢将工作中些积累形成文字2009-2-12 4:19:20疯狂代码 /。

用VB编写OPC客户端

用VB编写OPC客户端
Copyright Software Toolbox, 1999,2000,2001 All Rights Reserved Worldwide. Software Toolbox is a registered trademark of Software Toolbox, Inc.
OPC
Agenda
OPC - Review of the Basics OPC - Terminology OPC & VB 101 - Automation Wrapper & Object Model Building Your VB Client - Read data - 7 easy steps with code from start to finish Housekeeping Handles Handles Everywhere - how the server and client correlate the data each is managing in your program Writing Data Future ideas to consider New developments since original presentation in 10/99 Resources for future learning
The Automation Wrapper connects to the OPC server and creates the groups and items in the server and gives you references to them in your VB program in an Object model that mirrors that of the server

opc编程

opc编程

C++6.0环境下的OPC通信设计及其在控制系统中的应用Posted by admin十一月 24, 2009随着计算机技术和控制技术的不断发展,现代工业过程控制系统逐渐发展成为现场设备管理,过程管理和商业管理三个层次组成的系统,然而它们之间却存在相互通信的问题,其主要问题是不同的计算机系统(DCS,MIS等)的接口不统一、不标准,过程控制系统和信息系统各有专用技术接口以及API(应用程序接口)。

尽管可以编写定制的驱动程序和接口程序,但因不同类型硬件及软件包都需相互通信,使得驱动程序的种类迅速地增长,并且连接程序开发没有一个统一、开放的标准,不同程序间易相互冲突。

这种情况不仅增加了用户的负担,而且在实际上并不能真正解决不同系统的互操作性【1~2】。

出于对上述问题的考虑,1996年8月,一个由自动化领域的领先公司组成的工作组在Microsoft公司帮助下提出了一个基于微软 OLE,COM,DCOM,XML,Internet及Net技术的开放的、灵活的、即插即用的工业标准OPC【3】。

2 OPC技术简介2.1 OPC背景OPC(OLE for Process Control)是基于Microsoft公司的Distributed internet Application(DNA)构架和Component Object Model(COM)技术,根据易扩展性而设计的。

OPC规范定义了一个工业标准接口,该标准使得COM技术适用与过程控制和制造自动化等应用领域。

OLE原意即对象链接与嵌入,而现在的OLE包含了许多新的特征,如统一数据传输、结构化存储和自动化,已经成为独立于计算机语言、操作系统甚至硬件平台的一种规范。

PLC2.2 OPC接口结构OPC由两套接口组成:客户端和服务器程序员使用的OPC自定义接口(OPC COM Custom Interfaces);支持用高端商业应用开发的客户程序的OPC自动化接口(OPC OLE Automation Interfaces)。

VB编写OPC客户端程序

VB编写OPC客户端程序

如何用VB编写OPC客户端程序一、引言在工业自动化领域,计算机早已成为必不可少的工具,计算机技术的不断发展,大大加速了工业自动化技术的进步,而各种各样的工业控制应用软件正是具体实现这一进程的最重要的工具。

以往,应用软件开发商要为每一种硬件开发驱动程序,由于硬件的种类繁多,特征各异,软件开发商的负担异常繁重,尤其是如果硬件特征发生了变化,整个应用软件相应的驱动程序也要相应地修改,这对软件开发商,对整个工程都是很不利的。

而且由于驱动程序的不统一,不同应用程序访问同一硬件设备时常常发生冲突。

OPC(OLE for Process Control)技术标准正是在这种情况下产生的。

OPC 基于微软的OLE、COM和DCOM技术,而且它本身就是一种特殊的COM ,也正因为有微软的参与,以及以已经成熟的技术为基础,它比一般的工业标准制定的效率更高,它从开始制定到第一个可运行的规范开始运行,只用了不到一年的时间。

二、OPC原理及应用OPC技术为工业自动化软件面向对象的开发提供了统一的标准。

它大大减轻了软件开发商的负担,软件开发商不必再为每一硬件单独编写驱动程序,只要硬件的特征符合统一的OPC接口程序标准,或者硬件生产商提供OPC服务器,如图一所示,不同的应用软件开发商都可以采用OPC标准设计工控软件,以标准规定的统一接口通过OPC服务器存取现场数据。

这样,当现场设备发生变化或系统中加入新设备时,OPC服务器的提供商需要重新实现服务器接口,以适应硬件的变化,但由于服务器所提供的接口的一致性,工控软件不作更改即可继续使用,只是某些情况下可能需要重新组态(如添加新的PLC站点等),这样,软件开发商可以节省大量的时间致力于工控软件的性能方面的提高,不必再考虑硬件变化带来的影响,大大减小了软件维护的工作量。

这正如OPC规范里所说,OPC将应用软件和硬件设备划清了界限。

2.1 OPC基本结构OPC服务器有两类接口:定制接口(Custom Interface)、自动化接口(Automation Interface),定制接口比较低级,它提供更多的功能,效率也比后者高,可以用C++语言调用此类接口,自动化接口主要用于VB、DELPHI等开发工具。

C#编写OPC客户端读取OPC服务器的数据(最高效简洁版)

C#编写OPC客户端读取OPC服务器的数据(最高效简洁版)

C#编写OPC客户端读取OPC服务器的数据(最⾼效简洁版) List<string> ItemIds= new List<string>(){"S7-1200.0-166.BOOL","S7-1200.0-166.BYTE","S7-1200.0-166.INT","S7-1200.0-166.WORD","S7-1200.0-166.REAL",};//把需要订阅的项添加到group中。

for (int i = 0; i < ItemIds.Count; i++){OPCItem myItem = group.OPCItems.AddItem(ItemIds[i], i);}Console.ReadKey();}private static void Group_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps){//此处注意i是从1开始,因为getvalue没有0.下⾯输出分别为数据的ClientHandles(就是上⽂AddItem⽅法的第⼆个参数。

),Itemvalue 就是值,Qualities为质量,timestamps为时间。

for (int i = 1; i < NumItems+1; i++){Console.WriteLine(ClientHandles.GetValue(i).ToString() + "--" + ItemValues.GetValue(i).ToString() + "--" +Qualities.GetValue(i).ToString() + "--" + TimeStamps.GetValue(i).ToString());}}}}最终结果输出如下:这就是⼀个OPC客户端,我想应该是最简单的了。

Delphi7.0开发OPC客户端程序(Siemens_Opc_client)

Delphi7.0开发OPC客户端程序(Siemens_Opc_client)

OPC是OLE for Process Control的缩写,即把OLE应用于工业控制领域,OPC是建立在O LE规范之上,它为工业控制领域提供了一种标准的数据访问机制。

OPC服务器由三类对象组成:服务器(Server)、组(Group)、数据项(Item)。

服务器对象(Server)拥有服务器的所有信息,同时也是组对象(Group)的容器。

组对象(Group)拥有本组的所有信息,同时包容并逻辑组织OPC数据项(Item)。

在这里数据项(Item)就是指所有的PLC信号的输入与输出。

OPC组对象(Group)提供了客户组织数据的一种方法。

客户可对之进行读写,还可以设置客户端的数据更新速率。

当服务器缓冲区内的数据发生改变时,OPC将向客户发出通知,客户得到通知后再进行必要的处理。

而无须浪费大量的时间进行查询。

OPC规范定义了两种组对象:公共组和局部组(私有组)。

公共组由多个客户共有,局部组只隶属于一个OPC客户。

一般来说,客户和服务器的一对连接只需要定义一个组对象。

在每个组对象中,客户可以加入多个OPC数据项(Item)。

OPC数据项(Item)是服务器端定义的对象,通常指向设备的一个寄存器单元。

OPC客户对设备寄存器的操作都是通过其数据项来完成的,通过OPC数据项(Ite m),OPC规范尽可能地隐藏了设备的特殊信息,也使OPC服务器的通用性大大增强。

OPC 数据项(Item)并不提供对外接口,客户不能直接对之进行操作,所有的操作都是通过组对象进行的。

每个OPC数据项(Item)的数据结构包括三个成员变量:即数据值、数据质量和时间戳。

数据值是以Variant形式表示的。

Delphi7.0加载Siemens动态库:1.打开Delphi7.0,点击Project->Import Type Library2.在Import Type Library里面找到Siemens OPC DAAutomation 2.0 (Version 1.0),在Clas s Nams里面可以看三个类方法(TOPCGroups,TOPCGroup,TOPCServer),默认的Palette Page为ActiveX,单击Install…Delphi7.0中编写客户端程序:1.连接OPC服务器在Form上面添加三个OPC控件:OPCGroup1: TOPCGroup;OPCGroups1: TOPCGroups;OPCServer1: TOPCServer;具体操作图文说明请到网盘下载注:具体设备的OPC驱动虽然不一致,但是都有统一的标准,本文只是针对Siemens设备,如果有错误欢迎批评指教!。

OPC客户程序_VB同步

OPC客户程序_VB同步

End Sub
Private Function GetQualityText(Quality) As String
Select Case Quality
Case 0: GetQualityText = "BAD"
Case 64: GetQualityText = "UNCERTAIN"
OutText = "添加组"
Set GroupObj = ServerObj.OPCGroups.Add("Group")
OutText = "Adding an Item to the group"
Set ItemObj = GroupObj.OPCItems.AddItem("XXXITEM", 1)'XXXITEM为添加的ITEM名称
Command_Write.Enabled = True
Command_Exit.Enabled = True
OutText = "连接OPC服务器"
Set ServerObj = New OPCServer
ServerObj.Connect ("XXXSERVER")'XXXSERVER为某OPC服务器名称
End Sub
Private Sub Command_Write_Click()'同步写
Dim OutText As String
Dim Serverhandles(1) As Long
Dim MyValues(1) As Variant
Dim MyErrors() As Long

(C#)OPC客户端源码

(C#)OPC客户端源码

(C#)OPC客户端源码Code///摘要///程式使用C#.NET 2005 编写///引用类库OPCDAAuto.dll///OPCServer采用KEPWare///在windows xp sp2、sp3、windows 2003上测试通过///完成于:2008年12月31日///测试于:2009年01月05日//////作者:潇洒草///Email:zhkai868@///QQ:44649029//////如分发,请保留此摘要。

///鄙视那些拿代码当宝贝的人,鄙视那些你不拿源码换就不稀罕你的人,鄙视那些自私的人。

///别人看到你的代码,你能死啊?对你有多大威胁啊?强烈鄙视~~~///如果你是这样的人,赶紧关了。

偶不欢迎。

using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using ;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>/// </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();//获取本地计算机上的OPCServerNametry{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 };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服务器保留的系统项,此处可不做处理。

OPC客户端编程汇编

OPC客户端编程汇编

OPC编程汇编OPC客户端的自动化实现OPC是建立在COM,DCOM的基础商的,因此绝大多数语言都可以很好的进行开发。

在Net中开发客户端有以下几种方式:(1)使用OPCNetAPI,需要用到OPCNetAPI.dll,.dll(2)使用自动化接口,需要用到OPCDAAuto.dll(3)使用自定义接口,需要用到多个Wrapper:OpcRcw.Ae.dll,OpcRcw.Batch.dll,n.dll,OpcRcw.Da.dll,OpcRcw.Dx.dll,OpcRcw.Hda.dll,OpcRcw.Sec.dll以上开发方式所需的动态链接库可以从OPC基金会的网站上下载,一些下载项目可能需要注册,或成为基金会的成员。

不同的方式有各自的有缺点,请参见…本文使用自动化接口,语言进行开发,开发项目是无线射频(RFID)卡方面的应用,典型的如公交车,或公司考勤使用的刷卡机。

需要注意的是自动化接口存在一个“不是问题”的问题,数组下标是以1开始的,而不是传统计算机开发上的以0开始。

不知道设计者头脑是怎么想();这可能会给一些语言的开发造成问题(,没有你就是幸运的)需求:OPCDAAuto.dll或该Dll的Interop(一):客户端开发流程OPC客户端的开发主要遵循下图所示的开发流程,下面就从以下几个开发步骤进行说明(二):枚举OPC服务器列表枚举服务器主要是通过OPCServer接口的GetOPCServers方法来实现的,该方法会返回OPC服务器数组(以1为下界,上面已有说明),以下是代码段'枚举OPC服务器列表Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Loa dTryGlobalOPCServer = New OPCAutomation.OPCServerClass()Dim ServerList As Object= GlobalOPCServer.GetOPCServersFor index As Short= LBound(ServerList) To UBound(ServerList) '加入控件列表中,注意这里使用LBound和UBoundcbbServerList.Items.Add(ServerList(index))NextIf cbbServerList.Items.Count > 0 ThencbbServerList.SelectedIndex = 0End IfResetControlStatus() '设置控件状态GlobalOPCServer = NothingCatch Ex As ExceptionMessageBox.Show("List OPC servers failed: "+ Ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd Sub(三):连接OPC服务器自动化接口中连接到服务器是使用connect方法Public Overridable Sub Connect(ByVal ProgID As String, Optional ByVal Node As Object = Nothing)ProgID指服务器的ProgID,Node代表网络节点,如果是本机则放空即可。

OPC客户程序(VB篇——异步)

OPC客户程序(VB篇——异步)

OPC客户程序(VB篇——异步)建立如下窗体:引用如下:代码如下:Option ExplicitOption Base 1Const WRITEASYNC_ID = 1Const READASYNC_ID = 2Const REFRESHASYNC_ID = 3'----------------------------------------------------------------------------' Interface Objects'----------------------------------------------------------------------------Public WithEvents ServerObj As OPCServerPublic WithEvents GroupObj As OPCGroupDim ItemObj1 As OPCItemDim ItemObj2 As OPCItemDim Serverhandle(2) As LongPrivate Sub chkGroupActive_Click()If chkGroupActive = 1 ThenGroupObj.IsActive = 1ElseGroupObj.IsActive = 0End IfEnd SubPrivate Sub Command_Start_Click()Dim OutText As StringOn Error GoTo ErrorHandlerCommand_Start.Enabled = FalseCommand_Read.Enabled = TrueCommand_Write.Enabled = TrueCommand_Exit.Enabled = True chkGroupActive.Enabled = TrueOutText = "连接OPC服务器"Set ServerObj = New OPCServerServerObj.Connect ("XXXSERVER")OutText = "添加组"Set GroupObj = ServerObj.OPCGroups.Add("Group") GroupObj.IsSubscribed = TruechkGroupActive_ClickOutText = "添加ITEM"Set ItemObj1 = GroupObj.OPCItems.AddItem("XXXITEM1", 1) Set ItemObj2 = GroupObj.OPCItems.AddItem("XXXITEM2", 2)Serverhandle(1) = ItemObj1.ServerhandleServerhandle(2) = ItemObj2.ServerhandleExit SubErrorHandler:MsgBox Err.Description + Chr(13) + _OutText, vbCritical, "ERROR"End SubPrivate Sub Command_Read_Click() '异步读Dim OutText As StringDim myValue As VariantDim myQuality As VariantDim myTimeStamp As VariantDim ClientID As LongDim ServerID As LongDim ErrorNr() As LongDim ErrorString As StringOutText = "读值"ClientID = READASYNC_IDGroupObj.AsyncRead 1, Serverhandle, ErrorNr, ClientID, ServerIDIf ErrorNr(1) <> 0 ThenErrorString = ServerObj.GetErrorString(ErrorNr(1))MsgBox ErrorString, vbCritical, "Error AsyncRead()"End IfErase ErrorNrExit SubErrorHandler:MsgBox Err.Description + Chr(13) + _OutText, vbCritical, "ERROR"End SubPrivate Sub Command_Write_Click() '异步写Dim OutText As StringDim Serverhandles(1) As LongDim MyValues(1) As VariantDim ErrorNr() As LongDim ErrorString As StringDim Cancel_id As LongOutText = "Writing Value"MyValues(1) = Edit_WriteValGroupObj.AsyncWrite 1, Serverhandle, MyValues, ErrorNr, WRITEASYNC_ID, Cancel_idIf ErrorNr(1) <> 0 ThenErrorString = ServerObj.GetErrorString(ErrorNr(1))MsgBox ErrorString, vbCritical, "Error AsyncRead()"End IfErase ErrorNrExit SubErrorHandler:MsgBox Err.Description + Chr(13) + _OutText, vbCritical, "ERROR"End SubPrivate Sub Command_Exit_Click() '停止Dim OutText As StringOn Error GoTo ErrorHandlerCommand_Start.Enabled = TrueCommand_Read.Enabled = FalseCommand_Write.Enabled = FalseCommand_Exit.Enabled = FalsechkGroupActive.Enabled = FalseOutText = "Removing Objects"Set ItemObj1 = NothingSet ItemObj2 = NothingServerObj.OPCGroups.RemoveAllSet GroupObj = NothingServerObj.DisconnectSet ServerObj = NothingExit SubErrorHandler:MsgBox Err.Description + Chr(13) + _OutText, vbCritical, "ERROR"End Sub'异步读回调Private Sub GroupObj_AsyncReadComplete(ByVal TransactionID As Long, ByVal NumItems As Long, ClientHandles() As Long, ItemValues() As Variant, Qualities() As Long, TimeStamps() As Date, Errors() As Long)Dim ErrorString As StringIf (TransactionID = READASYNC_ID) ThenIf Errors(1) = 0 ThenEdit_ReadVal = ItemValues(1)Edit_ReadQu = GetQualityText(Qualities(1))Edit_ReadTS = TimeStamps(1)ElseErrorString = ServerObj.GetErrorString(Errors(1))MsgBox ErrorString, vbCritical, "Error AsyncReadComplete()"End IfEnd IfEnd Sub'异步写回调Private Sub GroupObj_AsyncWriteComplete(ByVal TransactionID As Long, ByVal NumItems As Long, ClientHandles() As Long, Errors() As Long)Dim ErrorString As StringIf (TransactionID = WRITEASYNC_ID) ThenIf Errors(1) = 0 ThenEdit_WriteRes = ServerObj.GetErrorString(Errors(1))ElseErrorString = ServerObj.GetErrorString(Errors(1))MsgBox ErrorString, vbCritical, "Error AsyncWriteComplete()"End IfEnd IfEnd Sub'回调Private Sub GroupObj_DataChange(ByVal TransactionID As Long, ByVal NumItems As Long, ClientHandles() As Long, ItemValues() As Variant, Qualities() As Long, TimeStamps() AsDate)Dim i As LongFor i = 1 To NumItemsEdit_OnDataVal(i - 1) = ItemValues(i)Edit_OnDataQu(i - 1) = GetQualityT ext(Qualities(i)) Edit_OnDataTS(i - 1) = TimeStamps(i)Next iEnd SubPrivate Function GetQualityText(Quality) As StringSelect Case QualityCase 0: GetQualityText = "BAD"Case 64: GetQualityText = "UNCERTAIN"Case 192: GetQualityText = "GOOD"Case 8: GetQualityText = "NOT_CONNECTED"Case 13: GetQualityText = "DEVICE_FAILURE"Case 16: GetQualityText = "SENSOR_FAILURE"Case 20: GetQualityText = "LAST_KNOWN"Case 24: GetQualityText = "COMM_FAILURE"Case 28: GetQualityText = "OUT_OF_SERVICE"Case 132: GetQualityText = "LAST_USABLE"Case 144: GetQualityText = "SENSOR_CAL"Case 148: GetQualityText = "EGU_EXCEEDED"Case 152: GetQualityText = "SUB_NORMAL" Case 216: GetQualityText = "LOCAL_OVERRIDE"Case Else: GetQualityText = "UNKNOWN ERROR" End SelectEnd Function。

关于OPCClient编写

关于OPCClient编写

关于OPCClient编写关于OPC Client 编写hapican 895 5热门 2014-02-23 20:14昨天又有人问我 OPC Client 编写,实际是他们不了解OPC 客户端的工作原理,要想写客户端程序,必须知道OPC对象,OPC逻辑对象模型包括3类对象:OPC server对象、OPC group对象、OPC item对象,每类对象都包括一系列接口。

OPC Server对象主要功能为:1、创建和管理OPC Group对象;2、管理服务器内部的状态信息;OPC Group对象主要功能为:1、管理OPC Group对象的内部状态信息;2、创建和管理Items对象。

3、OPC服务器内部的实时数据存取服务(同步与异步方式)。

OPC组中有以下几个主要属性:Name :组的名字;Active:组的激活状态标志;Update Rate OPC:服务器向客户程序提交数据变化的刷新速率;Percent Dead band:数据死区,即能引起数据变化的最小数值百分比。

OPC ITEM 是非COM对象,在OPC标准中用来描述实时数据,是客户端不可见的对象。

代表了与服务器中的数据的连接,它并不是数据源,而仅仅是与数据源的连接。

每个项都有以下主要属性:Active项的激活状态、Value项的数值、类型为VARIANT、Quality 项的品质,代表数值的可信度,类型为SHORT、TimeStamp时间戳,代表数据的存取时间。

你不管用什么开发语言只要了解上面几个对象,就会写程序了下面举个VC的例子HRESULT r1;CLSID clsid;LONG TimeBias = 0;FLOAT PercentDeadband = 0.0;DWORD RevisedUpdateRate;LPWSTR ErrorStr;char str[100];CString szErrorText;m_pItemResult = NULL;客户端程序必须对DCOM进行初始化设置,以保证OPC服务器端回调函数不会被堵塞。

(完整word版)OPCclient在VC环境下编程

(完整word版)OPCclient在VC环境下编程

OPC client 在VC环境下编程一.连接使用到变量的说明类型说明HRESULT 函数返回值,用来检测函数返回值(如:初始化COM库,查找CLSID,创建OPC服务等),提供函数执行情况CLSID 全球唯一标示符,用来确定OPC服务的标识,从注册表查找获得LPWSTR LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型.LPSTR被定义成是一个指向以NULL(‘\0')结尾的8位ANSI字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针OPC接口说明IOPCServer *m_IOPCServer;IOPCServer 接口及成员函数主要用于对组对象进行创建,删除,枚举和获取当前状态等操作.是OPC 服务器对象的主要接口.接口及成员IOPCItemMgt *m_IOPCItemMgt;IOPCItemMgt 接口及成员函数用于OPC 客户程序添加、删除和组对象中组员等控制操作。

IOPCSyncIO *m_IOPCSyncIO;IOPCSyncIO 用于同步数据访问。

OPCITEMDEF m_Items[1];OPCITEMDEF 数组,包含着项的存取路径, 定义和被请求的数据类OPCITEMRESULT *m_ItemResult;OPCITEMRESULT 数组,服务器用来告诉客户关于项的附加的信息(项句柄和规范的数据类型)OPCHANDLE m_GrpSrvHandle;OPC服务的句柄,在多个函数中都会用到使用到的函数说明CoInitialize(NULL); 初始化COM库CoInitialize是Windows提供的API函数,用来告诉Windows以单线程的方式创建com对象.应用程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。

返回值S_OK : 该线程中COM库初始化成功S_FALSE 该线程中COM库已经被初始化CoInit ialize () 标明以单线程方式创建。

opcvba源代码

opcvba源代码

opcvba源代码OptionE某plicitOptionBae1Contervername=\DimWithEventMyOPCServerAOPCServerDimWithEvent MyOPCGroupAOPCGroupDimMyOPCGroupCollAOPCGroupDimMyOPCItemCollAOP CItemDimMyOPCItemAOPCItemDimMyOPCItemAOPCItemDimclienthandle(6)A LongDimServerHandle()ALongDimValue(1)AVariantDimError()ALongDimI temID(6)AStringDimGroupNameAStringDimNodeNameAStringDimitemv(6)A VariantDimiiAInteger'华丽的分割线——————————————————'SubStartClient()'目的:链接至OPC_erver,创建组和添加条目'——————————————————————————————————————华丽的分割线SubStartClient()'OnErrorGotoErrorHandler'---------------可以自由选择ClientHandle和GroupNameForii=1To6 clienthandle(ii)=iiNe某tiiGroupName=\'-------------从单元\得到ItemIDNodeName=Range(\ItemID(1)=Range(\ItemID(2)=Range(\ItemID(3 )=Range(\ItemID(4)=Range(\ItemID(5)=Range(\ItemID(6)=Range(\ '----------------------------------得到一个OPC服务器的实例SetMyOPCServer=NewOPCServerMyOPCServer.Connectervername,NodeNameSetMyOPCGroupColl=MyOPC Server.OPCGroup'-----------------为添加组设置缺省的激活状态MyOPCGroupColl.DefaultGroupIActive=True'-----------------------添加组至收集SetMyOPCGroup=MyOPCGroupColl.Add(GroupName)SetMyOPCItemColl= MyOPCGroup.OPCItem'-----------------------添加一个条目、返回erverhandleMyOPCItemColl.AddItem6,ItemID(),clienthandle(),ServerHandle( ),Error'--------------------------用于接收不同的信息组MyOPCGroup.ISubcribed=TrueE某itSubErrorHadnler:MgBo某\EndSub'华丽的分割线-----------------------------------------------------------------------'SubStopClient()'目的:从服务器释放对象并且断开连接'-----------------------------------------------------------------------------------Subtopclient()'----------------------释放组合服务器对象MyOPCGroupColl.RemoveAll'----------------------与服务器断开连接并且清楚MyOPCServer.DiconnectSetMyOPCItemColl=NothingSetMyOPCGroup=Nothi ngSetMyOPCGroupColl=NothingSetMyOPCServer=NothingEndSub'华丽的分割线-----------------------------------------------------------------------'SubMyOPCGroup_DataChange()'目的:组中的数值、质量或时间标志改变时,该事件激活'华丽的分割线-----------------------------------------------------------------------'-------------------------如果OPC-DAAutomation2.1被安装,使用:itemv(clienthandle(ii))=itemvalue(ii)Ne某tiiRange(\Range(\Range(\Range(\Range(\EndSub。

delphi用Automation接口编写OPC客户端

delphi用Automation接口编写OPC客户端

delphi 用Automation接口编写OPC客户端一,首先是OPCAutomation 的安装1)使用regsvr32 注册 OPCDAAuto.dll2)在 Delphi 的project菜单中,选导入类型库 OPC Automation 2.0。

二编写程序声明 OPC 的类与接口FOPCServer:TOPCServer;FOPCGroup :TOPCGroup;FOPCb :OPCBrowser;FOPCItems :OPCItems; // interfaceFOPCItem :OPCItem; // interface// 获取OPC Server 列表function TForm1.OPCServerList(): Boolean;var OPCServerList,OPCServerName:OleVariant;j,i:integer;beginResult := false;tryFOPCServer := TOPCServer.Create(Self);OPCServerList:=FOPCServer.GetOPCServers;i:=VarArrayHighBound(OPCServerList,1);for j:=1 to i dobeginOPCServerName:=VarArrayGet(OPCServerList,j);lboxServerName.Items.Add(OPCServerName);end;exceptResult := False;end;end;// 连接OPC Serverfunction TForm1.OPCServerConnect(sServerID:string): Boolean; beginResult := true;tryFOPCServer.Connect1(sServerID);exceptResult := False;end;end;// 断开与OPC 服务器的连接procedure TForm1.OPCServerDisconnect;beginif Assigned(FOPCServer) thenbeginif Assigned(FOPCGroup) thenbeginFOPCServer.OPCGroups.RemoveAll;FOPCGroup.Free;FOPCGroup := nil;end;FOPCItems := nil;FOPCItem := nil;FOPCServer.Disconnect;FOPCServer.Free;FOPCServer := nil;end;end;// 创建连接OPC Groupfunction TForm1.OPCGroupConnect(AGroupName: OleVariant): Boolean; beginResult := True;tryFOPCGroup := TOPCGroup.Create(Self);FOPCGroup.ConnectTo(FOPCServer.OPCGroups.Add(AGroupName));FOPCGroup.UpdateRate :=1000;FOPCGroup.IsActive := True;FOPCGroup.IsSubscribed := True; // 事件支持exceptResult := False;end;end;procedure TForm1.BrowseItem(curNode:TTreeNode);var i: Integer;sItemName:WideString;beginwith FOPCb dobeginFilter:='*';DataType:=0;AccessRights:=0;ShowBranches;for i:=1 to Count dobeginsItemName:=Item(i);TvItemView.Items.AddChild(curNode,sItemName);end;// TvItemView.Selected.Expand(true);end;end;procedure TForm1.ADDBrowserItem;vari,iOrg:integer;sItemName:WideString;beginFOPCb:=FOPCServer.CreateBrowser;iOrg:=FOPCb.Get_Organization;if iOrg=2 then //平坦式结构beginwith FOPCb dobeginFilter:='*';DataType:=0;AccessRights:=0;ShowLeafs(true);for i:=1 to Count dobeginsItemName:=Item(i);TvItemView.Items.AddChild(SerVerNameNode,sItemName);end;end;endelse begin //树状结构BrowseItem(SerVerNameNode);end;end;procedure TForm1.SetBrowsePosition(sPosition:string);begintryFOPCb.MoveToRoot;caption:=sPosition;FOPCb.MoveDown(sPosition);except;end;end;procedure ItemViewClick(Sender: TObject);var i: Integer;sItemName:WideString;beginListBox1.Clear;SetBrowsePosition(TvItemView.Selected.Text);with FOPCb dobeginFilter:='*';DataType:=0;AccessRights:=0;ShowLeafs(true);for i:=1 to Count dobeginsItemName:=Item(i);ListBox1.Items.Add (sItemName);end;end;end;procedure ItemViewExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean);beginif not TvItemView.Selected.HasChildren thenbeginSetBrowsePosition(TvItemView.Selected.Text);BrowseItem(TvItemView.Selected);end;end;//添加一个项procedure TForm1.OPCItemAdd(sItemName:string);beginFOPCItems := FOPCGroup.OPCItems;FOPCItems.DefaultRequestedDataType:=0;FOPCItems.DefaultIsActive :=true;FOPCItem:=FOPCItems.AddItem(sItemName,ItemIndex);end;//读取指定项function TForm1.ReadData(ItemName:string):OleVariant;varValue, Quality, TimeStamp: OleVariant;beginFOPCitem :=FOPCItems.Item(ItemName);if not Assigned(FOPCItem) then Exit;FOPCItem.Read(OPCDevice, Value, Quality, TimeStamp);ReadData :=Value;end;。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

OPC编程汇编OPC客户端的自动化实现OPC是建立在COM,DCOM的基础商的,因此绝大多数语言都可以很好的进行开发。

在Net中开发客户端有以下几种方式:(1)使用OPCNetAPI,需要用到OPCNetAPI.dll,.dll(2)使用自动化接口,需要用到OPCDAAuto.dll(3)使用自定义接口,需要用到多个Wrapper:OpcRcw.Ae.dll,OpcRcw.Batch.dll,n.dll,OpcRcw.Da.dll,OpcRcw.Dx.dll,OpcRcw.Hda.dll,OpcRcw.Sec.dll以上开发方式所需的动态链接库可以从OPC基金会(/)的网站上下载,一些下载项目可能需要注册,或成为基金会的成员。

不同的方式有各自的有缺点,请参见…本文使用自动化接口,语言进行开发,开发项目是无线射频(RFID)卡方面的应用,典型的如公交车,或公司考勤使用的刷卡机。

需要注意的是自动化接口存在一个“不是问题”的问题,数组下标是以1开始的,而不是传统计算机开发上的以0开始。

不知道设计者头脑是怎么想(有人知道吗?);这可能会给一些语言的开发造成问题(有人碰到吗,没有你就是幸运的)需求:OPCDAAuto.dll或该Dll的Interop(一):客户端开发流程OPC客户端的开发主要遵循下图所示的开发流程,下面就从以下几个开发步骤进行说明(二):枚举OPC服务器列表枚举服务器主要是通过OPCServer接口的GetOPCServers方法来实现的,该方法会返回OPC服务器数组(以1为下界,上面已有说明),以下是代码段Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Loa dTryGlobalOPCServer = New OPCAutomation.OPCServerClass()Dim ServerList As Object= GlobalOPCServer.GetOPCServersFor index As Short= LBound(ServerList) To UBound(ServerList) '加入控件列表中,注意这里使用LBound和UBoundcbbServerList.Items.Add(ServerList(index))NextIf cbbServerList.Items.Count > 0 ThencbbServerList.SelectedIndex = 0End IfResetControlStatus() '设置控件状态GlobalOPCServer = NothingCatch Ex As ExceptionMessageBox.Show("List OPC servers failed: "+ Ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd Sub(三):连接OPC服务器自动化接口中连接到服务器是使用connect方法Public Overridable Sub Connect(ByVal ProgID As String, Optional ByVal Node As Object = Nothing)ProgID指服务器的ProgID,Node代表网络节点,如果是本机则放空即可。

连接到服务器后,以下属性需要特别注意:OPCServer.StartTime:服务器的启动时间OPCServer.CurrentTime:服务器的当前时间,各个客户端可以通过这个属性值完成一些同步的操作OPCGroups.DefaultGroupIsActive:以后添加的Group是否默认激活OPCGroups.DefaultGroupDeadBand:Group的默认死区,变化量超过死区后将会触发DataChange事件,合理的设置该值可以提高程序性能OPCGroups.Count:下属组(Group)的数量OPCGroups.DefaultGroupLocalID:组(Group)的默认通信区域编号,如1024OPCGroups.DefaultGroupUpdateRate:组(Group)的默认刷新率,该属性也比较重要OPCGroups.DefaultGroupTimeBias:组(Group)的默认时间偏差(四):添加组(Group)和项(Item)添加组和项需要用到Groups.Add和Items.AddItem方法,以下是原型:Function Add(Optional ByVal Name As Object = Nothing) As OPCAutomation.OPCGroupFunction AddItem(ByVal ItemID As String, ByVal ClientHandle As Integer) As OPCAutomation.OPCItem组也有两个重要的属性Group.UpdateRate:刷新率,该属性通Groups的UpdateRate意义一样,如果这个值有设置,则以这个值为准Group.IsSubscribed:是否使用订阅功能以下是代码段'连接到指定的OPC服务器Private Sub btnConnectServer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnectServer.ClickIf cbbServerList.Text <> ""ThenConnectedOPCServer = New OPCAutomation.OPCServerClass()TryConnectedOPCServer.Connect(cbbServerList.Text)ConnectedOPCServer.OPCGroups.DefaultGroupDeadband = 0'添加组ConnectedGroup = ConnectedOPCServer.OPCGroups.Add()ConnectedGroup.UpdateRate = 3 * 1000 '刷新虑,用于下面的DataChange事件ConnectedGroup.IsSubscribed = True'使用订阅功能'添加项GlobalOPCItems(0) = ConnectedGroup.OPCItems.AddItem("Reader_Device.OpenCard", 0)GlobalOPCItems(1) = ConnectedGroup.OPCItems.AddItem("Reader_Device.CloseCard", 1)GlobalOPCItems(2) = ConnectedGroup.OPCItems.AddItem("Reader_Device.CardNO", 2)RefreshServerStatus() '刷新服务器状态Catch ex As ExceptionConnectedOPCServer = NothingMessageBox.Show("OPC server connect failed : "+ ex.Message, "OPCSample", MessageBoxButtons.OK)End TryResetControlStatus()End IfEnd Sub(五):读写操作与事件控制读写操作包括同步和异步两种操作方式,以下是这几个方法的原型:Group的同步读事件Sub SyncRead(ByVal Source As Short, ByVal NumItems As Integer, ByRef ServerHandles As System.Array, ByRef Values As System.Array, ByRef Errors As System.Array, Optional ByRef Qualities As Object = Nothing, OptionalByRef TimeStamps As Object = Nothing)Group的同步写事件Sub SyncWrite(ByVal NumItems As Integer, ByRef ServerHandles As System.Array, ByRef Values As System.Array, ByRef Er rors As System.Array)Group的异步读事件Sub AsyncRead(ByVal NumItems As Integer, ByRef ServerHandles As System.Array, ByRef Errors As System.Array, ByVal Tr ansactionID As Integer, ByRef CancelID As Integer)Group的异步写事件Sub AsyncWrite(ByVal NumItems As Integer, ByRef ServerHandles As System.Array, ByRef Values As System.Array, ByRef Errors As System.Array, ByVal TransactionID As Integer, ByRef CancelID As Integer)如果使用异步的读写操作,那么还需要实现Group中的ReadComplete和WriteComplete两个事件PublicEvent AsyncReadComplete(ByVal TransactionID As Integer, ByVal NumItems As Integer, ByRef ClientHandles As System.Ar ray, ByRef ItemValues As System.Array, ByRef Qualities As System.Array, ByRef TimeStamps As System.Array, ByRef Errors As System.Array)PublicEvent AsyncWriteComplete(ByVal TransactionID As Integer, ByVal NumItems As Integer, ByRef ClientHandles As System.A rray, ByRef Errors As System.Array)其他相关的重要事件包括:Group数据变化时的通知事件PublicEvent DataChange(ByVal TransactionID As Integer, ByVal NumItems As Integer, ByRef ClientHandles As System.Array, ByR ef ItemValues As System.Array, ByRef Qualities As System.Array, ByRef TimeStamps As System.Array)Group的异步取消事件Public Event AsyncCancelComplete(ByVal CancelID As Integer)Server(服务器)关闭通知事件Public Event ServerShutDown(ByVal Reason As String)以下是这些实现的代码段'读取卡片指定的块号的值Private Sub btnReadCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) If Not(ConnectedGroup Is Nothing) ThenTry'获取块号Dim BlockNo As Short= CByte(ReadBlockNo.Text)'如果要获取数据的块所对应的项还没有创建,就创建它If GlobalOPCBlockItems(BlockNo) Is Nothing ThenGlobalOPCBlockItems(BlockNo) =ConnectedGroup.OPCItems.AddItem("Reader_Device.Block"& CStr(BlockNo), 200 + BlockNo)End If'准备参数数组Dim ServerResults As System.ArrayDim ServerErrors As System.ArrayDim ServerHandles(1) As IntegerServerHandles(1) = GlobalOPCBlockItems(BlockNo).ServerHandle'读取值ConnectedGroup.SyncRead(OPCAutomation.OPCDataSource.OPCDevice, 1, ServerHandles, ServerResults, ServerErrors)If ServerErrors(1) <> 0 ThenMsgBox("Read Card Failed:"& ServerErrors(1))ElsetxtReadBlockNo.Text = ServerResults(1)End IfCatch ex As ExceptionMessageBox.Show("OPC server Read Card failed: "+ ex.Message, "OPCSample", MessageBoxButtons.OK)End TryEnd IfEnd Sub'写卡片指定块的值Private Sub btnWriteCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) If Not(ConnectedGroup Is Nothing) ThenTry'获取块号If GlobalOPCBlockItems(BlockNo) Is Nothing ThenGlobalOPCBlockItems(BlockNo) =ConnectedGroup.OPCItems.AddItem("Reader_Device.Block"& CStr(BlockNo), 200 + BlockNo)End If'准备参数数组Dim ServerValues(1) As ObjectDim ServerErrors As ArrayDim ServerHandles(1) As IntegerServerHandles(1) = GlobalOPCBlockItems(BlockNo).ServerHandleServerValues(1) = txtWriteBlockNo.Text'写入值ConnectedGroup.SyncWrite(1, ServerHandles, ServerValues, ServerErrors)If ServerErrors(1) <> 0 ThenMsgBox("Write Card Failed:"& ServerErrors(1))ElseMsgBox("Write Card Succeed")End IfCatch ex As ExceptionMessageBox.Show("OPC server Write Card failed: "+ ex.Message, "OPCSample", MessageBoxButtons.OK)End TryEnd IfEnd Sub(六):断开服务器断开服务器只要使用OPCServer的Disconnect方法几个,以下是代码段:'断开到指定OPC服务器的连接Private Sub btnDisconnectServer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Hand les btnDisconnectServer.ClickIf Not(ConnectedOPCServer Is Nothing) ThenTryConnectedOPCServer.Disconnect()Catch ex As ExceptionMessageBox.Show("OPC server disconnect failed: "+ ex.Message, "OPCSample", MessageBoxButtons.OK)FinallyConnectedOPCServer = NothingResetControlStatus()End TryEnd IfEnd Sub(七):相关链接非常好的一个OPC技术网站/OPC基金会网址/国内的一个比较好的OPC网站/Index.html(八):全部源码Dim GlobalOPCServer As OPCAutomation.OPCServerClassDim WithEvents ConnectedOPCServer As OPCAutomation.OPCServerClassDim WithEvents ConnectedGroup As OPCAutomation.OPCGroupClassDim GlobalOPCItems(4) As OPCAutomation.OPCItemDim GlobalOPCBlockItems(64) As OPCAutomation.OPCItem'枚举OPC服务器列表Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadTryGlobalOPCServer = New OPCAutomation.OPCServerClass()Dim ServerList As Object = GlobalOPCServer.GetOPCServersFor index As Short = LBound(ServerList) To UBound(ServerList) '加入控件列表中,注意这里使用LBound和UBoundcbbServerList.Items.Add(ServerList(index))NextIf cbbServerList.Items.Count > 0 ThencbbServerList.SelectedIndex = 0End IfResetControlStatus() '设置控件状态GlobalOPCServer = NothingCatch Ex As ExceptionMessageBox.Show("List OPC servers failed: " + Ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd Sub'连接到指定的OPC服务器Private Sub btnConnectServer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConne ctServer.ClickIf cbbServerList.Text <> "" ThenConnectedOPCServer = New OPCAutomation.OPCServerClass()TryConnectedOPCServer.Connect(cbbServerList.Text)'设置组集合的默认属性ConnectedOPCServer.OPCGroups.DefaultGroupIsActive = TrueConnectedOPCServer.OPCGroups.DefaultGroupDeadband = 0'添加组ConnectedGroup = ConnectedOPCServer.OPCGroups.Add()ConnectedGroup.UpdateRate = 3 * 1000 '刷新虑,用于下面的DataChange事件ConnectedGroup.IsSubscribed = True'使用订阅功能'添加项GlobalOPCItems(0) = ConnectedGroup.OPCItems.AddItem("Reader_Device.OpenCard", 0)GlobalOPCItems(1) = ConnectedGroup.OPCItems.AddItem("Reader_Device.CloseCard", 1)GlobalOPCItems(2) = ConnectedGroup.OPCItems.AddItem("Reader_Device.CardNO", 2)RefreshServerStatus() '刷新服务器状态Catch ex As ExceptionConnectedOPCServer = NothingMessageBox.Show("OPC server connect failed : " + ex.Message, "OPCSample", MessageBoxButtons.OK) End TryResetControlStatus()End Sub'服务器断开事件通知Private Sub OnServerShutDown(ByVal Reason As String) Handles ConnectedOPCServer.ServerShutDownbtnDisconnectServer_Click(Nothing, New EventArgs())End SubPrivate Sub OnGroupDataChange(ByVal TransactionID As Integer, ByVal NumItems As Integer, ByRef ClientHandles As System.Array, ByRef ItemValues As System.Array, ByRef Qualities As System.Array, ByRef TimeStamps As System.Arr ay) Handles ConnectedGroup.DataChangeFor i As Integer = 1 To NumItemsIf Qualities(i) = OPCAutomation.OPCQuality.OPCQualityGood ThenSelect Case ClientHandles(i)Case 2txtCardNo.Text = CStr(ItemValues(i))Case 200 '测试7张卡片txtValueBlock0.Text = CStr(ItemValues(i))Case 201txtValueBlock1.Text = CStr(ItemValues(i))Case 202txtValueBlock2.Text = CStr(ItemValues(i))Case 203txtValueBlock3.Text = CStr(ItemValues(i))Case 204txtValueBlock4.Text = CStr(ItemValues(i))Case 205txtValueBlock5.Text = CStr(ItemValues(i))Case 206txtValueBlock6.Text = CStr(ItemValues(i))Case 207txtValueBlock7.Text = CStr(ItemValues(i))Case ElseEnd SelectEnd IfNextEnd Sub'断开到指定OPC服务器的连接Private Sub btnDisconnectServer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDis connectServer.ClickIf Not (ConnectedOPCServer Is Nothing) ThenTryConnectedOPCServer.Disconnect()Catch ex As ExceptionMessageBox.Show("OPC server disconnect failed: " + ex.Message, "OPCSample", MessageBoxButtons.OK) FinallyConnectedOPCServer = NothingResetControlStatus()End TryEnd If'开卡,并返回卡号Private Sub btnOpenCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)If ConnectedGroup IsNot Nothing ThenTry'准备参数数组Dim ServerHandles(1) As IntegerDim ServerValues(1) As ObjectDim ServerErrors As System.ArrayServerHandles(1) = GlobalOPCItems(0).ServerHandleServerValues(1) = 1'写入值,用于执行OpenCard的操作ConnectedGroup.SyncWrite(1, ServerHandles, ServerValues, ServerErrors)If ServerErrors(1) <> 0 ThenMsgBox("OpenCardError: " & ServerErrors(1))End IfServerHandles(1) = GlobalOPCItems(2).ServerHandleDim ServerResult As System.Array'读取卡号ConnectedGroup.SyncRead(OPCAutomation.OPCDataSource.OPCDevice, 1, ServerHandles, ServerResult, Server Errors)If ServerErrors(1) <> 0 ThenMsgBox("ReadCardNoError: " & ServerErrors(1))ElsetxtCardNo.Text = ServerResult(1)End IfCatch ex As ExceptionMessageBox.Show("OPC server Open Card failed: " + ex.Message, "OPCSample", MessageBoxButtons.OK) End TryResetControlStatus()End IfEnd Sub'读取卡片指定的块号的值Private Sub btnReadCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)If Not (ConnectedGroup Is Nothing) ThenTry'获取块号Dim BlockNo As Short = CByte(ReadBlockNo.Text)'如果要获取数据的块所对应的项还没有创建,就创建它If GlobalOPCBlockItems(BlockNo) Is Nothing ThenGlobalOPCBlockItems(BlockNo) = ConnectedGroup.OPCItems.AddItem("Reader_Device.Block" & CStr(Block No), 200 + BlockNo)End If'准备参数数组Dim ServerResults As System.ArrayDim ServerErrors As System.ArrayDim ServerHandles(1) As IntegerServerHandles(1) = GlobalOPCBlockItems(BlockNo).ServerHandle'读取值ConnectedGroup.SyncRead(OPCAutomation.OPCDataSource.OPCDevice, 1, ServerHandles, ServerResults, ServeIf ServerErrors(1) <> 0 ThenMsgBox("Read Card Failed:" & ServerErrors(1))ElsetxtReadBlockNo.Text = ServerResults(1)End IfCatch ex As ExceptionMessageBox.Show("OPC server Read Card failed: " + ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd IfEnd Sub'写卡片指定块的值Private Sub btnWriteCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)If Not (ConnectedGroup Is Nothing) ThenTry'获取块号Dim BlockNo As Short = CByte(WriteBlockNo.Text)'如果要写入数据的块所对应的项还没有创建,就创建它If GlobalOPCBlockItems(BlockNo) Is Nothing ThenGlobalOPCBlockItems(BlockNo) = ConnectedGroup.OPCItems.AddItem("Reader_Device.Block" & CStr(Block No), 200 + BlockNo)End If'准备参数数组Dim ServerValues(1) As ObjectDim ServerErrors As ArrayDim ServerHandles(1) As IntegerServerHandles(1) = GlobalOPCBlockItems(BlockNo).ServerHandleServerValues(1) = txtWriteBlockNo.Text'写入值ConnectedGroup.SyncWrite(1, ServerHandles, ServerValues, ServerErrors)If ServerErrors(1) <> 0 ThenMsgBox("Write Card Failed:" & ServerErrors(1))ElseMsgBox("Write Card Succeed")End IfCatch ex As ExceptionMessageBox.Show("OPC server Write Card failed: " + ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd IfEnd Sub'重设控件状态Private Sub ResetControlStatus()If ConnectedOPCServer Is Nothing ThenbtnConnectServer.Enabled = TruebtnDisconnectServer.Enabled = FalsebtnReadCard.Enabled = FalsebtnWriteCard.Enabled = FalsebtnOpenCard.Enabled = FalsebtnCloseCard.Enabled = FalseReadBlockNo.Value = 0WriteBlockNo.Value = 0txtCardNo.Text = ""txtSrvStartTime.Text = ""txtSrvCurrTime.Text = ""txtSrvGroupCount.Text = ""txtSrvGroupDeadBand.Text = ""txtSrvGroupDefActive.Text = ""txtSrvGroupLocalID.Text = ""txtSrvGroupTimeBias.Text = ""txtSrvRequestRate.Text = ""ElsebtnConnectServer.Enabled = FalsebtnDisconnectServer.Enabled = TrueIf txtCardNo.Text = "" ThenbtnReadCard.Enabled = FalsebtnWriteCard.Enabled = FalsebtnOpenCard.Enabled = TruebtnCloseCard.Enabled = FalseElsebtnReadCard.Enabled = TruebtnWriteCard.Enabled = TruebtnOpenCard.Enabled = TruebtnCloseCard.Enabled = TrueEnd IfEnd IfEnd Sub'刷新服务器状态属性信息Private Sub RefreshServerStatus()If ConnectedOPCServer IsNot Nothing ThentxtSrvStartTime.Text = ConnectedOPCServer.StartTime.ToString()txtSrvCurrTime.Text = ConnectedOPCServer.CurrentTime.ToString()With ConnectedOPCServer.OPCGroupstxtSrvGroupCount.Text = CStr(.Count)txtSrvGroupDeadBand.Text = CStr(.DefaultGroupDeadband)If .DefaultGroupIsActive ThentxtSrvGroupDefActive.Text = "True"ElsetxtSrvGroupDefActive.Text = "False"End IftxtSrvGroupLocalID.Text = CStr(.DefaultGroupLocaleID)txtSrvGroupTimeBias.Text = CStr(.DefaultGroupTimeBias)txtSrvRequestRate.Text = CStr(.DefaultGroupUpdateRate)End WithEnd IfEnd Sub'关闭卡片Private Sub btnCloseCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) If ConnectedGroup IsNot Nothing ThenTryDim ServerHandles(1) As IntegerDim ServerValues(1) As ObjectServerHandles(1) = GlobalOPCItems(1).ServerHandleServerValues(1) = 1ConnectedGroup.SyncWrite(1, ServerHandles, ServerValues, ServerErrors)If ServerErrors(1) <> 0 ThenMsgBox("Close Card Error: " & ServerErrors(1))End IfCatch ex As ExceptionMessageBox.Show("OPC server Close Card failed: " + ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd IfEnd SubEnd ClassPrerequisites: ComboBox control named cbbServerList, Button1 and Button2 on Form1.Code BlockPublic Class Form1Dim GlobalOPCServer As OPCAutomation.OPCServerClassDim WithEvents ConnectedOPCServer As OPCAutomation.OPCServerClassDim WithEvents ConnectedGroup As OPCAutomation.OPCGroupClassPrivate Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles MyBase.Load TryGlobalOPCServer = New OPCAutomation.OPCServerClass()Dim ServerList As Object = GlobalOPCServer.GetOPCServersFor index As Short = LBound(ServerList) To UBound(ServerList)cbbServerList.Items.Add(ServerList(index))NextIf cbbServerList.Items.Count > 0 ThencbbServerList.SelectedIndex = 0End IfGlobalOPCServer = NothingCatch Ex As ExceptionMessageBox.Show("List OPC servers failed: " + Ex.Message, "OPCSample", MessageBoxButtons.OK)End TryEnd Sub' Connect to OPC serverPrivate Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles Button1.Cl ickIf cbbServerList.Text <> ""ThenConnectedOPCServer = New OPCAutomation.OPCServerClass()TryConnectedOPCServer.Connect(cbbServerList.Text)'Set property for Group connectionConnectedOPCServer.OPCGroups.DefaultGroupIsActive = TrueConnectedOPCServer.OPCGroups.DefaultGroupDeadband = 0'Add groupConnectedGroup = ConnectedOPCServer.OPCGroups.Add()ConnectedGroup.UpdateRate = 3 * 1000ConnectedGroup.IsSubscribed = True'Add itemsGlobalOPCItems(0) = ConnectedGroup.OPCItems.AddItem("Reader_Device.OpenCard", 0)GlobalOPCItems(1) = ConnectedGroup.OPCItems.AddItem("Reader_Device.CloseCard", 1)GlobalOPCItems(2) = ConnectedGroup.OPCItems.AddItem("Reader_Device.CardNO", 2)Catch ex As ExceptionConnectedOPCServer = NothingMessageBox.Show("OPC server connect failed : " + ex.Message, "OPCSample", MessageBoxButtons.OK) End TryEnd IfEnd Sub' Disconnect to OPC serverPrivate Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles Button2.Cl ickIf Not (ConnectedOPCServer Is Nothing) ThenTryConnectedOPCServer.Disconnect()Catch ex As ExceptionMessageBox.Show("OPC server disconnect failed: " + ex.Message, "OPCSample", MessageBoxButtons.OK) FinallyConnectedOPCServer = NothingEnd TryEnd If End Sub End ClassHierarchyThe OPC server and the client application communicate each other through the interface of COM. The root class is OPC server object, and it accesses the group object and the item object by using this class.The device datas of PLC (ex. 'X0' and 'D0' etc.) are constructed at the low hierarchy, and you can access the device datas as the unit of item or collection.Register OPC automation dllWhen the OPC server is set up, DLL necessary for OPC is automatically registered. For access to OPC Server from Visual Basic, it needs to check "OPC Automation 2.0".Declare OPC Objects (OPC Server / OPC Group / OPC Item)For hooking events of OPC Server, add to "WithEvents" in dimension statement or event handler named "OBJECTNAME_EVENTNAME".Dim WithEvents Myserver As OPCServerDim WithEvents Mygroup As OPCGroupDim WithEvents Mygroups As OPCGroupsDim Myitem As OPCItemDim Myitems As OPCItemsDim MyBrowser As OPCBrowserGet OPC Server ListIt is able to get installed OPC Server name by using OPC Server object. In this sample, it shows OPC Server name in list box and operator can select the target server.Dim Getserver As OPCServerDim Servers As VariantSet Getserver = New OPCServerServers = Getserver.GetOPCServersFor i = LBound(Servers) To UBound(Servers)List1.AddItem Servers(i)Next iSet Getserver=NothingIt is able to get device name registered in OPC Server by using OPC Server object. You can make the Group under device and OPC Server object is enabled to access this lower layer.Set Myserver = New OPCServerMyserver.Connect ServerName.Text, NodeName.TextSet MyBrowser = Myserver.CreateBrowserMyBrowser.ShowBranchesDim bname As VariantFor Each bname In MyBrowserItemList.AddItem "+" & bnameNext nameFor accessing client application to physical device data, it needs to generate OPC Group object in OPC group collection. The OPC Group object can configure update interval of tags. Normally, the device of accessing same cycle will register in same group. Also, you should be carefully CPU performance to create over groups because OPC Server create a thread for each group.Dim ClientHandles(16) As LongDim OPCItemIDs(16) As StringSet Mygroups = Myserver.OPCGroupsSet Mygroup = Mygroups.Add("Group1")Mygroup.UpdateRate = "1000"Mygroup.IsActive = FalseFor i = 1 To 16ClientHandles(i) = iOPCItemIDs(i) = "Device1" + ".D" + Format(i)Next iSet Myitems = Mygroup.OPCItemsMyitems.AddItems 16, OPCItemIDs, ClientHandles, ItemServerHandles, ItemServerErrorsMygroup.IsActive = TrueImplements event handler of OPC Group object for advice mode. The OPC Server read data for each cycle and if changing the value, callback to client application. The quality flag is normally '0xC0', when occurred error, it will be turn to other value. Mygroup.IsSubscribed = TruePublic Sub Mygroup_DataChange(ByVal TID As Long, _ByVal NumItems As Long, Chd() As Long, ItemValues() As Variant, _Qualities() As Long, TimeStamps() As Date)For i = 1 To NumItemsDebug.print ItemValues(i) + ":" + TimeStamps(i) + _":" + Qualities(i)Next iEnd SubThe OPC has two ways of data access, Synchronize and Asynchronous. In Synchronize, the client application must be wait for completing server work. But the client application can confirm server transaction is normally completed because the OPC Server returns the result on completing the communication work. This is a normally style of procedure.In Asynchronous mode, the OPC Server turns the handle to client as soon as receiving the request and proceed the transaction on background. After completing this work, calls handler of client application. Asynchronous mode cut down wait time for communication and be able to run client application.Caution: Asynchronous access is enabled under advice mode.'Sync ReadMygroup.SyncRead OPCDevice, 16, ItemServerHandles, ItemValues, ItemServerErrors, ItemQualities, ItemTimeStampsFor i = 1 To 16Debug.print ItemValues(i) + ":" + ItemTimeStamps(i) + ":" + ItemQuality(i)Next i'Sync WriteFor i = 1 To 16ItemVal(i) = iNext iMygroup.SyncWrite 16, ItemServerHandles, ItemVal, ItemServerErrorsFor i = 1 To 16If ItemServerErrors(i) <> 0 ThenMsgBox "Write ERROR " + Format(i)End IfNext i'Async Read(TransactionID=10, CancelID=11)Mygroup.AsyncRead 16, ItemServerHandles, ItemServerErrors, 10, 11Private Sub Mygroup_AsyncReadComplete(ByVal TransactionID As Long, ByVal NumItems As Long, _ClientHandles() As Long, ItemValues() As Variant, Qualities() As Long, _TimeStamps() As Date, Errors() As Long)Debug.print "AsyncRead Comp" + Chr$(9) + Time$ + Chr$(13) + Chr$(10)End Sub'Async WriteDim ItemVal(ItemCount) As VariantFor i = 1 To ItemCountItemVal(i) = iNext iMygroup.AsyncWrite 16, ItemServerHandles, ItemVal, ItemServerErrors, 100, 101Private Sub Mygroup_AsyncWriteComplete(ByVal TransactionID As Long, _ByVal NumItems As Long, ClientHandles() As Long, Errors() As Long)Debug.print "AsyncWrite Comp" + Chr$(9) + Time$ + Chr$(13) + Chr$(10)End SubIn cache read operation, OPC Server doesn't access the physical device and return the last data on memory. The OPC Server read and caches the value every each time.It will be able to access on high speed if not need newest value.Mygroup.SyncRead OPCCache, 16, ItemServerHandles, ItemValues, ItemServerErrors, ItemQualities, ItemTimeStampsFor i = 1 To 16Debug.print ItemValues(i) + ":" + ItemTimeStamps(i) + ":" + ItemQuality(i)Next iI am trying to develop an opc - da client using .net technology.Have gone through the documents on opc and opc client and all,but am still not sure how to implement it, can someone give me a direction on how to start with it?59 Answers FoundAnswer 1can you please provide some additional details on exactly what you're trying to do and any other relevant info that I can pass on to our support engineer?thanks,-brenda (ISV Buddy Team)Answer 2Hey Ksona,I was just speaking to a college of mine about DA cleints this morning. Have your checked out the opc Exchange at/ ?I know that Eric Murphy is an OPC genius, and he can probably give you a hand, or point you in a great direction.You can also email me and I can see if one of my college's has some time to help you out? I'm curious as to what devices you are trying to access?Answer 3Genius? That's a wee bit over the top, let's just say I've experienced a thing or two about OPC. However, if you're fishing for a response, flattery will get you everywhere :)As the other replies pointed out, the question is a bit open ended. 'using .NET technology' offers a few possibilites, depending on your develpoment language C#, , managed C++, etc.The easiest way, would be to make use of the OPC client .NET wrapper supplied by the OPC Foundation. You do have to be a member to access this, however that offers other advantages such as invitations to the OPC Interoperabilty events to test your client against other vendors.If that's not an option, I have seen applications that make use of the OPC Automation dll. This was originally intended for VB apps, but some vendors have upgraded the automation interface to work with You would have to ask specifically because not all versions do.Otherwise, you are looking at writing an application that interfaces to unmanaged COM interfaces. From an programatic point of view, an OPC client would be no different from any other COM client. If you're new to OPC, this is not a trivial task...。

相关文档
最新文档