*(00)*

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
来源:https://blog.csdn.net/ryanzll/article/details/42109739
 
准备工作
下载   Opc.NET Api,可以从 OPC Foundation网站,也可以google,csdn上也有。下载到安装包之后,安装即可,相应的文件会拷贝到
“C:\Windows\assembly\GAC_MSIL\OpcNetApi\2.0.2.0__9a40e993cbface53\OpcNetApi.dll”
“C:\Windows\assembly\GAC_MSIL\OpcNetApi.Com\2.0.1.0__9a40e993cbface53\OpcNetApi.Com.dll”
...
这样在这台电脑上的所有.net项目都可以使用   Opc.NET Api了。但这也有不方便的地方,如果是团队开发,那么就要求团队所有人都必须按照这个库。那么你也可以把这些dll从GAC里面放到你工程的第三方库中,然后让工程的引用指向那里就可以了。
BTW:只要在本地新建个指向本机”C$\Windows “的网络映射,然后通过这个映射就可以任性的操作这些文件了。
 
新建工程
打开VS,新建c#工程,并添加OpcNetApi.dll,OpcNetApi.Com.dll的引用
 
读写数据项(Item)
 
        static void Main( string [] args)
        {
            // Create a server object and connect to the TwinCATOpcServer
            Opc. URL url = new Opc. URL ( "opcda://localhost/BECKHOFF.TwinCATOpcServerDA" );
            Opc.Da. Server server = null ;
            OpcCom. Factory fact = new OpcCom. Factory ();
            server = new Opc.Da. Server (fact, null );
            server.Connect(url, new Opc. ConnectData ( new System.Net. NetworkCredential ()));
 
            // Create a group
            Opc.Da. Subscription group;
            Opc.Da. SubscriptionState groupState = new Opc.Da. SubscriptionState ();
            groupState.Name = "Group" ;
            groupState.Active = false ;
            group = (Opc.Da. Subscription )server.CreateSubscription(groupState);
 
            // add items to the group
            Opc.Da. Item [] items = new Opc.Da. Item [3];
            items[0] = new Opc.Da. Item ();
            items[0].ItemName = "PLC1.Value1" ;
            items[1] = new Opc.Da. Item ();
            items[1].ItemName = "PLC1.Value2" ;
            items[2] = new Opc.Da. Item ();
            items[2].ItemName = "PLC1.Value3" ;
            items = group.AddItems(items);
 
            // write items
            Opc.Da. ItemValue [] writeValues = new Opc.Da. ItemValue [3];
            writeValues[0] = new Opc.Da. ItemValue ();
            writeValues[1] = new Opc.Da. ItemValue ();
            writeValues[2] = new Opc.Da. ItemValue ();
            writeValues[0].ServerHandle = group.Items[0].ServerHandle;
            writeValues[0].Value = 0;
            writeValues[1].ServerHandle = group.Items[1].ServerHandle;
            writeValues[1].Value = 0;
            writeValues[2].ServerHandle = group.Items[2].ServerHandle;
            writeValues[2].Value = 0;
            Opc. IRequest req;
            group.Write(writeValues, 321, new Opc.Da. WriteCompleteEventHandler (WriteCompleteCallback), out req);
 
            // and now read the items again
            group.Read(group.Items, 123, new Opc.Da. ReadCompleteEventHandler (ReadCompleteCallback), out req);
            Console .ReadLine();
        }
 
        static void WriteCompleteCallback( object clientHandle, Opc. IdentifiedResult [] results)
        {
            Console .WriteLine( "Write completed" );
            foreach (Opc. IdentifiedResult writeResult in results)
            {
                Console .WriteLine( "\t{0} write result: {1}" , writeResult.ItemName, writeResult.ResultID);
            }
            Console .WriteLine();
        }
 
        static void ReadCompleteCallback( object clientHandle, Opc.Da. ItemValueResult [] results)
        {
            Console .WriteLine( "Read completed" );
            foreach (Opc.Da. ItemValueResult readResult in results)
            {
                Console .WriteLine( "\t{0}\tval:{1}" , readResult.ItemName, readResult.Value);
            }
            Console .WriteLine();
        }
 
这里有个要注意的地方,在创建 Opc.Da.Subscription 的时候,会设置其Name属性,这个名称仅仅是给 Subscription 个名字,与OPC服务器中的组(group)名是两回事。
同时,在创建Item的时候,如果它是属于某个group的话,在设置其ItemName属性的时候,需要加上group的名字。
下面以MatrikonOPC Server for Simulation为例,如下图。当中有个名为"Group"的组,其下面有名为“Item”数据项,那么连接这个服务器,创建Item的时候,Item的名字应该是“ New_Intouch_000.Item ”。否则连接不上的,但是大小写貌似不区分的。
监视数据项变化(subscriptions)
所谓监视数据项变化,就是添加关心的数据项,也可设定更新频率,然后当这些数据项的值变化时就会通知你(事件机制)。

        static void Main(string[] args)

        {

            // Create a server object and connect to the TwinCATOpcServer

            Opc.URL url = new Opc.URL("opcda://localhost/BECKHOFF.TwinCATOpcServerDA");

            Opc.Da.Server server = null;

            OpcCom.Factory fact = new OpcCom.Factory();

            server = new Opc.Da.Server(fact, null);

 

            server.Connect(url, new Opc.ConnectData(new System.Net.NetworkCredential()));

 

 

            // Create a group

            Opc.Da.Subscription group;

            Opc.Da.SubscriptionState groupState = new Opc.Da.SubscriptionState();

            groupState.Name = "Group";

            groupState.Active = true;

            group = (Opc.Da.Subscription)server.CreateSubscription(groupState);

 

 

            // add items to the group.

            Opc.Da.Item[] items = new Opc.Da.Item[3];

            items[0] = new Opc.Da.Item();

            items[0].ItemName = "PLC1.dyn_R8[1]";

            items[1] = new Opc.Da.Item();

            items[1].ItemName = "PLC1.dyn_R4[1]";

            items[2] = new Opc.Da.Item();

            items[2].ItemName = "PLC1.dyn_I4[1]";

 

            items = group.AddItems(items);

 

            group.DataChanged += new Opc.Da.DataChangedEventHandler(OnTransactionCompleted);

            Console.ReadLine();

        }

 

        static void OnTransactionCompleted( object group, object hReq, Opc.Da.ItemValueResult[] items)

        {

            Console.WriteLine("------------------->");

            Console.WriteLine("DataChanged ...");

            for (int i = 0; i < items.GetLength(0); i++)

            {

                Console.WriteLine("Item DataChange - ItemId: {0}", items[i].ItemName);

                Console.WriteLine(" Value: {0,-20}", items[i].Value);

                Console.WriteLine(" TimeStamp: {0:00}:{1:00}:{2:00}.{3:000}",

                items[i].Timestamp.Hour,

                items[i].Timestamp.Minute,

                items[i].Timestamp.Second,

                items[i].Timestamp.Millisecond);

            }

            Console.WriteLine("-------------------<");

            }
如果需要撤销监视,可以通过“Array.Clear(subscription.Items,0,subscription.Items.Length)”的方式。此外添加监视必须调用Subscription.AddItems函数,通过直接修改Subscription.Items的方式貌似无效。
“OnTransactionCompleted”第一次被调用会传回所有监视项(很好理解,如果都没有变化,你怎么知道当前是什么值),第二次及以后 传回的是监视的数据项中变化项。
 

//删除仪表
//Opc.Da.Item[] items1 = new Opc.Da.Item[1];
//items1[0] = items[1];
//group.RemoveItems(items1);

 

posted on 2020-11-20 16:17  *(00)*  阅读(1369)  评论(0编辑  收藏  举报