1、1. OPC 对象的分层结构OPC 数据访问提供从数据源读取和写入特定数据的手段。OPC 数据访问对象是由下图所示的分层结构构成。即一个 OPC 服务器对象(OPCServer )具有一个作为子对象的 OPC 组集合对象(OPCGroups) 。在这个 OPC 组集合对象里可以添加多个的 OPC 组对象(OPCGroup) 。各个 OPC 组对象具有一个作为子对象的 OPC 标签集合对象(OPCItems) 。在这个 OPC 标签集合对象里可以添加多个的 OPC 标签对象(OPCItem) 。此外,作为选用功能,OPC 服务器对象还可以包含一个 OPC 浏览器对象(OPCBrowser) 。
2、OPC 对象中的最上层的对象是 OPC 服务器。一个 OPC 服务器里可以设置一个以上的OPC 组。OPC 服务器经常对应于某种特定的控制设备。例如,某种 DCS 控制系统,或者某种 PLC 控制装置。OPC 组是可以进行某种目的数据访问的多个的 OPC 标签的集合,例如某监视画面里所有需要更新的位号变量。正因为有了 OPC 组,OPC 应用程序就可以以同时需要的数据为一批的进行数据访问,也可以以 OPC 组为单位启动或停止数据访问。此外 OPC组还提供组内任何 OPC 标签的数值变化时向 OPC 应用程序通知的数据变化事件(表 1-4) 。服 务 器(OPCServer)浏 览 器(OPCB
3、rowser )组 集 合 (OPCGroups )组(OPCGroup)项 集 合(OPCItems)项(OPCItem)2. OPC 客户端搭建过程(部分代码)1) 连接服务器a) 查询服务器端主机的名字。string hostname = Dns.GetHostName();b) 初始化服务器对象,搜索主机上的服务器 ID,并枚举出来。public void searchlocalsvr(string hostName)/寻找本地服务器 tryOPCSvr = new OPCServer();object serverList = OPCSvr.GetOPCServers(hostNam
4、e);foreach (string server in (Array)serverList)Console.WriteLine(“本地 OPC 服务器:0“, server);catch (Exception err)Console.WriteLine(“枚举本地 OPC 服务器出错:0“, err.Message);c) 连接服务器。public void ctOPCSever(string HostName)/连接 OPC 服务器string OPCSvrName;searchlocalsvr(HostName);Console.WriteLine(“请输入要连接的服务器名字: “);O
5、PCSvrName = Console.ReadLine();tryOPCSvr.Connect(OPCSvrName, “);Console.WriteLine(“连接服务器成功!“);catch (Exception err)Console.WriteLine(“连接本地 OPC 服务器出错:0“, err.Message);2) 创建组(OPCGroups)对象和添加数据项对象(OPCItems)public void CreateGrp()/创建组对象tryOPCGrps = OPCSvr.OPCGroups;OPCGrp = new OPCAutomation.OPCGroup2;O
6、PCGrp0 = OPCGrps.Add(“G1“);OPCGrp1 = OPCGrps.Add(“G2“);SetGroupProperty();/OPCGrp0.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange);/OPCGrp0.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete);OPCGrp0.AsyncReadComplete += new DIO
7、PCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete);Console.WriteLine(“创建组成功!“);catch (Exception err)Console.WriteLine(“错误信息:0“, err);public void SetGroupProperty()OPCSvr.OPCGroups.DefaultGroupIsActive = true;/激活组。OPCSvr.OPCGroups.DefaultGroupDeadband = 0;/ 死区值,设为 0 时,服务器端该组内任何数据变化都通知
8、组。OPCSvr.OPCGroups.DefaultGroupUpdateRate = 200;/默认组群的刷新频率为200msOPCGrp0.UpdateRate = 100;/刷新频率为 1 秒。OPCGrp0.IsSubscribed = true;/使用订阅功能,即可以异步,默认 falsepublic void addItems()/添加数据项OPCIts = OPCGrp0.OPCItems;OPCIt = new OPCItem4;OPCIt0 = OPCIts.AddItem(“Integer.TAG_I0“, 1);OPCIt1 = OPCIts.AddItem(“Integ
9、er.TAG_I1“, 2);/OPCIt1 = OPCIts.AddItem(“Item2“, 0);/OPCIt2 = OPCIts.AddItem(“Item3“, 0);/OPCIt3 = OPCIts.AddItem(“Item4“, 0);Console.WriteLine(“添加数据项成功!“);3) 创建浏览器对象由于服务器端的菜单是树形结构,可以通过创建浏览器对象,一步步浏览菜单,寻找需要浏览的 Item。public void CrteBrowser()string branch;OPCBrowser OPCBrsr = OPCSvr.CreateBrowser();OPC
10、Brsr.ShowBranches();OPCBrsr.ShowLeafs(true);foreach (object turn in OPCBrsr)Console.WriteLine(“服务端浏览 :“ + turn.ToString();Console.WriteLine(“请需要浏览的分支:“);branch = Console.ReadLine();OPCBrsr.MoveDown(branch);OPCBrsr.ShowBranches();OPCBrsr.ShowLeafs(true);foreach (object turn in OPCBrsr)Console.WriteLi
11、ne(“服务端:“ + turn.ToString();4) 读取服务器端数据信息读取服务端数据信息包括同步读取和异步读取两种方式异步读取与同步读取的区别:同步读取适合用来读取少量数据,而异步读取可以读取大量数据而对运行不影响。因为程序运行过程中,调用同步读取函数,直到数据访问结果返回到客户程序之前,客户程序都处于等待之中。异步读取在被调用后,方法几乎立即返回。OPC 应用程序随后可以进行其他处理。当 OPC 服务器完成数据访问时,触发 OPC 应用程序的异步访问完成事件,将数据访问结果传送给 OPC 应用程序。但是可以看出同步数据访问相比起来更加容易实现,异步数据访问比较麻烦。A. 同步读取
12、(可以直接调用 Item 对象的 read 方法,或者调用组对象的 syncread 方法)public void SRead(string itemid)/同步读取object ItemValues; object Qualities; object TimeStamps;OPCIt0 = OPCIts.AddItem(itemid, 0);OPCIt0.Read(1, out ItemValues, out Qualities, out TimeStamps);Console.WriteLine(“同步读取数据结果如下:“);Console.WriteLine(“ID:0 Vaule:1
13、Quality:2 Timestamp:3“, OPCIt0.ItemID,Convert.ToString(ItemValues),Convert.ToString(Qualities),Convert.ToString(TimeStamps);B. 异步读取public void AsRead(string itemid)/异步读取OPCIt0 = OPCIts.AddItem(itemid, 0);int temp = new int 0, OPCIt0.ServerHandle ;Array serverHandles = (Array)temp;Array Errors;int ca
14、ncelID;OPCGrp0.AsyncRead(1, ref serverHandles, out Errors, 1, out cancelID);异步读取并不直接输出读取结果而是调用下面的函数void GroupAsyncReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Error
15、s)Console.WriteLine(“异步读取数据结果如下:“);for (int i = 1; i = NumItems; i+)Console.WriteLine(“ID:0 Vaule:1Quality:2 Timestamp:3“,OPCIti-1.ItemID,Convert.ToString(ItemValues.GetValue(i), Convert.ToString(Qualities.GetValue(i), Convert.ToString(TimeStamps.GetValue(i);在异步读取函数完成之后调用本函数,输出数据读取结果。5) 断开与服务器连接断开服务器得先清除所有组对象及其下的数据项对象。public void disconnectSvr()/与断开服务器tryOPCSvr.OPCGroups.RemoveAll();OPCSvr.Disconnect();Console.WriteLine(“OPC 服务器已断开!“);catch (Exception err)Console.WriteLine(err.Message);3. 程序运行样例运行结果如下所示: