OPCDAAuto.dll的C#使用方法浅析

上次研究了.Net版本的OPC API dll,这次我采用OPCDAAuto.dll来介绍使用方法。
以下为我的源代码,有详细的注释无需我多言。
编译平台:VS2008SP1、WINXP、KEPServer
除此之外,我也安装了西门子的Net2006和Step7,其中Net2006是负责OPC的,可能会在系统中创建一些dll之类的,并提供几个OPC服务器
以下是我Program.cs(基于控制台的)的全部内容,仍旧采用C#语言:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections;
using OPCAutomation;
using System.Threading;

namespace OPCDAAutoTest
{
    class Tester
    {
        static void Main(string[] args)
        {
            Tester tester=new Tester();
            tester.work();
        }
        #region 私有变量
        /// <summary>
        /// OPCServer Object
        /// </summary>
        OPCServer MyServer;
        /// <summary>
        /// OPCGroups Object
        /// </summary>
        OPCGroups MyGroups;
        /// <summary>
        /// OPCGroup Object
        /// </summary>
        OPCGroup MyGroup;
        OPCGroup MyGroup2;
        /// <summary>
        /// OPCItems Object
        /// </summary>
        OPCItems MyItems;
        OPCItems MyItems2;
        /// <summary>
        /// OPCItem Object
        /// </summary>
        OPCItem[] MyItem;
        OPCItem[] MyItem2;
        /// <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
        //测试用工作方法
        public void work()
        {
            //初始化item数组
            MyItem = new OPCItem[4];
            MyItem2 = new OPCItem[4];

            GetLocalServer();
            //ConnectRemoteServer("TX1", "KEPware.KEPServerEx.V4");//用计算机名的局域网
            //ConnectRemoteServer("192.168.1.35", "KEPware.KEPServerEx.V4");//用IP的局域网
            if (ConnectRemoteServer("", "KEPware.KEPServerEx.V4"))//本机
            {
                if (CreateGroup())
                {
                    Thread.Sleep(500);//暂停线程以让DataChange反映,否则下面的同步读可能读不到
                    //以下同步写
                    MyItem[3].Write("I love you!");//同步写
                    MyItem[2].Write(true);//同步写
                    MyItem[1].Write(-100);//同步写
                    MyItem[0].Write(120);//同步写              
   
                    //以下同步读
                    object ItemValues;  object Qualities; object TimeStamps;//同步读的临时变量:值、质量、时间戳
                    MyItem[0].Read(1,out ItemValues,out Qualities,out TimeStamps);//同步读,第一个参数只能为1或2
                    int q0 = Convert.ToInt32(ItemValues);//转换后获取item值
                    MyItem[1].Read(1, out ItemValues, out Qualities, out TimeStamps);//同步读,第一个参数只能为1或2
                    int q1 = Convert.ToInt32(ItemValues);//转换后获取item值
                    MyItem[2].Read(1, out ItemValues, out Qualities, out TimeStamps);//同步读,第一个参数只能为1或2
                    bool q2 = Convert.ToBoolean(ItemValues);//转换后获取item值
                    MyItem[3].Read(1, out ItemValues, out Qualities, out TimeStamps);//同步读,第一个参数只能为1或2
                    string q3 = Convert.ToString(ItemValues);//转换后获取item值,为防止读到的值为空,不用ItemValues.ToString()

                    Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                    Console.WriteLine("0-{0},1-{1},2-{2},3-{3}",q0,q1,q2,q3);

                    //以下为异步写
                    //异步写时,Array数组从下标1开始而非0!
                    int[] temp = new int[] { 0,MyItem[0].ServerHandle,MyItem[1].ServerHandle,MyItem[2].ServerHandle, MyItem[3].ServerHandle };
                    Array serverHandles = (Array)temp;
                    object[] valueTemp = new object[5] { "",255,520,true, "Love" };
                    Array values = (Array)valueTemp;
                    Array Errors;
                    int cancelID;
                    MyGroup.AsyncWrite(4, ref serverHandles, ref values, out Errors, 1, out cancelID);//第一参数为item数量
                    //由于MyGroup2没有订阅,所以以下这句运行时将会出错!
                    //MyGroup2.AsyncWrite(4, ref serverHandles, ref values, out Errors, 1, out cancelID);

                    //以下异步读
                    MyGroup.AsyncRead(4, ref serverHandles, out Errors, 1, out cancelID);//第一参数为item数量


                    /*MyItem[0] = MyItems.AddItem("BPJ.Db1.dbb96", 0);//byte
                    MyItem[1] = MyItems.AddItem("BPJ.Db1.dbw10", 1);//short
                    MyItem[2] = MyItems.AddItem("BPJ.Db16.dbx0", 2);//bool
                    MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string*/

 

 

                    Console.WriteLine("************************************** hit <return> to Disconnect...");
                    Console.ReadLine();  
                    //释放所有组资源
                    MyServer.OPCGroups.RemoveAll();
                    //断开服务器
                    MyServer.Disconnect();
                }
            }


            //END
            Console.WriteLine("************************************** hit <return> to close...");
            Console.ReadLine();  
        }
        //枚举本地OPC服务器
        private void GetLocalServer()
        {
            //获取本地计算机IP,计算机名称
            strHostName = Dns.GetHostName();
            //或者通过局域网内计算机名称
            strHostName = "TX1";

            //获取本地计算机上的OPCServerName
            try
            {
                MyServer = new OPCServer();
                object serverList = MyServer.GetOPCServers(strHostName);

                foreach (string server in (Array)serverList)
                {
                    //cmbServerName.Items.Add(turn);
                    Console.WriteLine("本地OPC服务器:{0}", server);
                }
            }
            catch (Exception err)
            {
                Console.WriteLine("枚举本地OPC服务器出错:{0}",err.Message);
            }
        }
        //连接OPC服务器
        /// <param name="remoteServerIP">OPCServerIP</param>
        /// <param name="remoteServerName">OPCServer名称</param>
        private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
        {
            try
            {
                MyServer.Connect(remoteServerName, remoteServerIP);//连接本地服务器:服务器名+主机名或IP

                if (MyServer.ServerState == (int)OPCServerState.OPCRunning)
                {
                    Console.WriteLine("已连接到:{0}",MyServer.ServerName);
                }
                else
                {
                    //这里你可以根据返回的状态来自定义显示信息,请查看自动化接口API文档
                    Console.WriteLine("状态:{0}",MyServer.ServerState.ToString());
                }
                MyServer.ServerShutDown+=ServerShutDown;//服务器断开事件
            }
            catch (Exception err)
            {
                Console.WriteLine("连接远程服务器出现错误:{0}" + err.Message);
                return false;
            }
            return true;
        }
        //创建组
        private bool CreateGroup()
        {
            try
            {
                MyGroups = MyServer.OPCGroups;
                MyGroup = MyServer.OPCGroups.Add("测试");//添加组
                MyGroup2 = MyGroups.Add("测试2");
                OPCGroup MyGroup3 = MyGroups.Add("测试3");//测试删除组
                //以下设置组属性
                {
                    MyServer.OPCGroups.DefaultGroupIsActive = true;//激活组。
                    MyServer.OPCGroups.DefaultGroupDeadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组。
                    MyServer.OPCGroups.DefaultGroupUpdateRate = 200;//默认组群的刷新频率为200ms
                    MyGroup.UpdateRate = 100;//刷新频率为1秒。
                    MyGroup.IsSubscribed = true;//使用订阅功能,即可以异步,默认false
                }       

                MyGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange);
                MyGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete);
                MyGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete);
                //由于MyGroup2.IsSubscribed是false,即没有订阅,所以以下的DataChange回调事件不会发生!
                MyGroup2.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange2);
                MyGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete); 
                 
                MyServer.OPCGroups.Remove("测试3");//移除组
                AddGroupItems();//设置组内items         
            }
            catch (Exception err)
            {
                Console.WriteLine("创建组出现错误:{0}", err.Message);
                return false;
            }
            return true;
        }
        private void AddGroupItems()//添加组
        {
            //itmHandleServer;
            MyItems = MyGroup.OPCItems;
            MyItems2 = MyGroup2.OPCItems;

            //添加item
            MyItem[0] = MyItems.AddItem("BPJ.Db1.dbb96", 0);//byte
            MyItem[1] = MyItems.AddItem("BPJ.Db1.dbw10", 1);//short
            MyItem[2] = MyItems.AddItem("BPJ.Db16.dbx0", 2);//bool
            MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string
            //移除组内item
            Array Errors;      
            int []temp=new int[]{0,MyItem[3].ServerHandle};
            Array serverHandle = (Array)temp;
            MyItems.Remove(1, ref serverHandle, out Errors);
            MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string

            MyItem2[0] = MyItems2.AddItem("BPJ.Db1.dbb96", 0);//byte
            MyItem2[1] = MyItems2.AddItem("BPJ.Db1.dbw10", 1);//short
            MyItem2[2] = MyItems2.AddItem("BPJ.Db16.dbx0", 2);//bool
            MyItem2[3] = MyItems2.AddItem("BPJ.Db11.S0", 3);//string

        }
        public void ServerShutDown(string Reason)//服务器先行断开
        {
            Console.WriteLine("服务器已经先行断开!");
        }
        /// <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>1    `
        void GroupDataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            Console.WriteLine("++++++++++++++++DataChanged+++++++++++++++++++++++");
            /*for (int i = 1; i <= NumItems; i++)
            {
                Console.WriteLine("item值:{0}", ItemValues.GetValue(i).ToString());
                //Console.WriteLine("item句柄:{0}", ClientHandles.GetValue(i).ToString());
                //Console.WriteLine("item质量:{0}", Qualities.GetValue(i).ToString());
                //Console.WriteLine("item时间戳:{0}", TimeStamps.GetValue(i).ToString());
                //Console.WriteLine("item类型:{0}", ItemValues.GetValue(i).GetType().FullName);
            }*/
        }
        void GroupDataChange2(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            Console.WriteLine("----------------------DataChanged2------------------");
            /*for (int i = 1; i <= NumItems; i++)
            {
                Console.WriteLine("item2值:{0}", ItemValues.GetValue(i).ToString());
                //Console.WriteLine("item2质量:{0}", Qualities.GetValue(i).ToString());
                //Console.WriteLine("item2时间戳:{0}", TimeStamps.GetValue(i).ToString());             
            }*/
        }
        /// <summary>
        /// 异步写完成
        /// 运行时,Array数组从下标1开始而非0!
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="Errors"></param>
        void GroupAsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
        {
            Console.WriteLine("%%%%%%%%%%%%%%%%AsyncWriteComplete%%%%%%%%%%%%%%%%%%%");
            /*for (int i = 1; i <= NumItems; i++)
            {
                Console.WriteLine("Tran:{0}   ClientHandles:{1}   Error:{2}", TransactionID.ToString(), ClientHandles.GetValue(i).ToString(), Errors.GetValue(i).ToString());
            }*/
        }

        /// <summary>
        /// 异步读完成
        /// 运行时,Array数组从下标1开始而非0!
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="ItemValues"></param>
        /// <param name="Qualities"></param>
        /// <param name="TimeStamps"></param>
        /// <param name="Errors"></param>
        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 Errors)
        {
            Console.WriteLine("****************GroupAsyncReadComplete*******************");
            for (int i = 1; i <= NumItems; i++)
            {
                //Console.WriteLine("Tran:{0}   ClientHandles:{1}   Error:{2}", TransactionID.ToString(), ClientHandles.GetValue(i).ToString(), Errors.GetValue(i).ToString());
                Console.WriteLine("Vaule:{0}",Convert.ToString(ItemValues.GetValue(i)));
            }
        }
    }
}

### 回答1: ++编写的全面介绍。 opcdaauto.dll是一种使用C++编写的Windows DLL文件,它是OPC自动化核心组件库的一部分。 OPC自动化是指使用微软所定义的基于COM和DCOM的技术,通过程序化方式实现与OPC服务器进行通信的方法opcdaauto.dll为其它组件提供了一些基础服务,以便它们可以通过DCOM连接到OPC服务器并获取数据。该DLL文件使得OPC自动化可以更容易地实现数据交换。 当使用opcdaauto.dll库时,C++程序员需要创建一个COM对象并使用现有的OPC服务器连接到其接口。使用DLL文件,程序员可以直接访问OPC服务器和其数据点,而无需了解服务器和客户端之间的复杂交互过程。 在使用opcdaauto.dll时,C++程序员可以自由选择使用所需的版本,以及根据自身的应用程序需求,进行自定义修改和应用。使用opcdaauto.dll库,C++程序员可以获得高效可靠的通信,轻松实现数据交换,从而为其它应用程序提供更灵活高效的数据获取手段。 总之,opcdaauto.dll作为OPC自动化核心组件库的一部分,是一个强大的DLL文件。使用C++编写的该DLL文件,可以在Windows操作系统上提供高效的通信,为用户带来方便,同时也为C++程序员在应用程序中取得成功的基本服务。 ### 回答2: OPC自动化组件opcdaauto.dll是一种用于实现OPC自动化的动态链接库文件。它提供了一组可供开发人员调用和使用的功能接口,以帮助他们开发和实现OPC自动化应用程序。 OPC DA是"数据访问"标准,其允许应用程序从数据源中读取或写入数据。 OPC DA自动化维护了一些标准接口,可以让应用程序直接调用和使用器COM对象。调用这些接口的最常用方法使用opcdaauto.dll使用opcdaauto.dll,开发人员可以编写各种支持数据访问或数据源和一些常规操作的应用程序。一些应用程序例子包括工业实时控制,监测和其他领域的数据采集和处理。opcdaauto.dll还支持多线程操作和多个客户端同时使用数据源,可以使得许多不同的客户端同时访问数据源。 对于开发人员而言,使用opcdaauto.dll是相对容易的,因为它提供了简便的COM接口。开发人员需要了解如何通过COM接口与OPC DA自动化器进行交互以及如何实现相应的回调方法。对于新手开发者,OPC DA CAB告诉用户如何实现opcdaauto.dll的用户控件,例如可以通过VB脚本或其他编程语言使用。同时,可以找到很多完整的例子,使用它们可以熟悉opcdaauto.dll的基本使用方法。 ### 回答3: OPC(OLE for Process Control)是一种用于工业自动化的标准通信协议。OPC DAData Access)是OPC的一种子协议,用于实时数据的读取和写入。opcdaauto.dll是一个OPC DA自动化客户端库,可用于连接到OPC服务器并读取数据。 使用C++编程语言可以调用opcdaauto.dll库中的函数来实现与OPC服务器的通信。首先,需要加载opcdaauto.dll库,然后使用CoInitialize函数初始化COM(Component Object Model)运行时库,以便调用COM接口。接下来,使用CLSIDFromProgID函数获取OPC服务器的CLSID(Class ID),并使用CoCreateInstance函数创建一个与OPC服务器的连接。通过IOPCServer接口,可以查询OPC服务器上的所有标签(Items),并使用IOPCSyncIO接口同步读取或写入标签的值。读取或写入完成后,需要使用CoUninitialize函数关闭COM运行时库并释放与OPC服务器的连接。 除了opcdaauto.dll库,还有许多其他的OPC DA客户端库可供选择,例如opcdaclient.dll、QT OpcUa Client SDK等。选择哪一种库取决于具体应用的需求和开发人员的编程能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值