博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用OPCAutomation实现对opc数据的访问
阅读量:6621 次
发布时间:2019-06-25

本文共 6350 字,大约阅读时间需要 21 分钟。

hot3.png

最近项目中需要 C#通过OPC方式获取数据,折腾了一段时间,第三方提供OPCServer虚拟环境,我创建C#客户端。

服务端是力控电子系统,第三方软件,不多做赘述,本文主要讲解OPC客户端的搭建和OPC连接步骤。

调用OPCAutomation类访问OPCServer端,并进行可控制读取间隔的OPC数据读取、存储工作。

本文主要介绍OPCAutomation类的使用。

简单流程如下:

1.创建OPC server的连接

2.创建OPC组对象并初始化设置

3.获取组的OPCItems对象,为读取数据做准备

4.opcltem的操作

5.退出程序的资源释放

 

创建连接很简单,需要指定OPCServer所在的服务器(内网可以指定IP或者计算机名),指定OPC服务的名称(同一服务器可能运行多个OPC服务以适配不同的下位机)

//通过timer获取OPCServer端数据void TimerTick(object sender, EventArgs e){	//连接OPCServer	KepServer.Connect(remoteServerName, remoteServerIP);	if (KepServer.ServerState == (int)OPCServerState.OPCRunning)	{	    label1.Text = "已连接到-" + KepServer.ServerName + "   ,starttime:" + KepServer.StartTime.ToString();		//创建并设置组        bool bSucce = this.CreateAndSetGroup();        //goup添加items        AddGroupItems();		//采集opc数据			GetOPCData();	    }else{            label1.Text = "OPC服务器状态异常: " + KepServer.ServerState.ToString();        }}

其中KepServer.Connect(remoteServerName, remoteServerIP);即OPCAutomation类提供的连接方法。

需要注意的是,在实际配置时,需要完全对OPC服务端所在服务器上配置防火墙出入站规则后,OPC服务才能够被其它服务器上的中间件访问到。

创建组相当于读取OPC上特定的项目,而具体的数据值是在每个项目下根据开发人员的定义而确定。

//创建组并设置组信息        private bool CreateAndSetGroup()        {            try            {                KepGroups = KepServer.OPCGroups;                KepGroup = KepGroups.Add("PCAuto.OPCServer");                KepServer.OPCGroups.DefaultGroupIsActive = true;//激活组                KepServer.OPCGroups.DefaultGroupDeadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组                KepGroup.IsSubscribed = true;//使用订阅功能,即可以异步,默认false                //绑定写操作的事件                KepGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete);                KepItems = KepGroup.OPCItems;            }            catch (Exception ex)            {            }            return true;        }

这段代码是为OPCGroup对象进行初始化。PCAuto.OPCServer为组名,激活组,使用订阅功能,绑定写操作的时间等等。

异步读完成 运行时,Array数组从下标1开始而非0!

//异步读完成 运行时,Array数组从下标1开始而非0!        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)        {            try            {            	//C# Dictionary 字典                 Dictionary
tagValueMap = new Dictionary
(); for (int i = 1; i <= NumItems; i++) { string clientHandle = ClientHandles.GetValue(i).ToString(); string tag = MAP_CLIENTHANDLE_TAG[clientHandle]; string val = ItemValues.GetValue(i).ToString(); //C# Dictionary 字典 添加数据 tagValueMap.Add(tag, val); } //构建json string json = ParseOPCData(tagValueMap); } catch (Exception ex) { } }

为全局变量OPCGroup添加items,在OPC中,每个opcltem会被分配一个客户端句柄值,同时会被配置上服务器句柄。几乎所有有关获取指定Opcltem对象的方法均要求指定客户端句柄值。

上图中有一C# Dictionary 字典,暂不做赘述,待下回分解。

//goup添加items        string[] sensorIdArray;        void  AddGroupItems()        {        	List
l_str = new List
(); //读取配置文件,获取需要的传感器ID string sensorIdList = getSensorId(); sensorIdArray = sensorIdList.Replace("\r\n","").Split(','); foreach (string sensorId in sensorIdArray){ l_str.Add(sensorId+"_COS"); l_str.Add(sensorId+"_DL1"); l_str.Add(sensorId+"_DL2"); l_str.Add(sensorId+"_DL3"); l_str.Add(sensorId+"_DL4"); l_str.Add(sensorId+"_IA"); l_str.Add(sensorId+"_IB"); l_str.Add(sensorId+"_IC"); l_str.Add(sensorId+"_P"); l_str.Add(sensorId+"_Q"); l_str.Add(sensorId+"_UAB"); l_str.Add(sensorId+"_UBC"); l_str.Add(sensorId+"_UCA"); } List
ItemsAdded = new List
(); int n = 0; MAP_CLIENTHANDLE_TAG = new Dictionary
(); foreach (string tag in l_str){ ItemsAdded.Add(KepItems.AddItem(tag + ".PV", n)); //clientHandle tag关系 MAP_CLIENTHANDLE_TAG.Add(n + "", tag); n++; } OPC_ITEMS_ADDED = ItemsAdded.ToArray(); }

OPCServer服务端数据源item

5d779ca4750f9a8f1971203f48bd4819bff.jpg

这段代码设计为了获取到全部的OPCltem所添加到所创建的OPCGroup对象的opcitem集合中,得到添加到goup中的item(OPC_ITEMS_ADDED)。

通过OPC_ITEMS_ADDED采集opc数据

//采集opc数据        private void GetOPCData()        {            try            {                //异步读opc数据                int[] temp = new int[OPC_ITEMS_ADDED.Length + 1];                temp[0] = 0;                for (int i = 1; i <= OPC_ITEMS_ADDED.Length; i++)                {                    temp[i] = OPC_ITEMS_ADDED[i - 1].ServerHandle;                }                Array serverHandles = (Array)temp;                Array Errors;                int cancelID;                Random rd = new Random();                int TransactionID = rd.Next(1, 10);                KepGroup.AsyncRead(serverHandles.Length - 1, ref serverHandles, out Errors, TransactionID, out cancelID);//第一参数为item数量            }            catch (Exception ex)            {       	                MessageBox.Show(ex.Message);            }        }

解析OPC数据并以json格式存储在本地

//解析opc数据        private string ParseOPCData(Dictionary
tagValueMap) { string filename = "E:\\mine\\下峪口\\data\\electric_data.txt"; StringBuilder builder = new StringBuilder(); string rowStr = ""; string time = ConvertDateTimeToInt(DateTime.Now).ToString(); rowStr += "["; foreach (string sensorId in sensorIdArray){ rowStr += "{\r\n\"id\":"+ "\"" + sensorId + "\",\r\n"; rowStr += "\"substation\":"+"\"假变电所\""+",\r\n"; rowStr += "\"timestamp\":"+time+",\r\n"; foreach (var item in tagValueMap) { string key = item.Key; string[] data = item.Key.Split('_'); string title = data[0]; string word = data[1]; if(title.Equals(sensorId)){ rowStr += "\""+ word + "\""+ ":" + item.Value + ",\r\n"; } } rowStr += "},"; } rowStr += "]"; rowStr = rowStr.Replace(",\r\n}","\r\n}").Replace(",]","]"); builder.Append(rowStr); File.WriteAllText(@filename, builder.ToString(), Encoding.GetEncoding("gb2312")); return ""; }

 

转载于:https://my.oschina.net/u/4006148/blog/2872746

你可能感兴趣的文章
超适合小白的python新手教程
查看>>
年过四十、零基础学前端开发,歪果仁是如何从教师转行程序员的?
查看>>
教你大数据必修三大技能 快快记录下来
查看>>
网络卡顿怎么办?
查看>>
Factom(公证通)--基于区块链的存证系统
查看>>
prezi,mfc,toefl,java
查看>>
Software AG成功整合Terracotta
查看>>
centos中进程管理工具
查看>>
【Prince2科普】Prince2的七大原则(7)
查看>>
从【BZOJ4173】谈做题技巧
查看>>
学JS的心路历程-函式(六)其余参数及预设参数
查看>>
[Ting's笔记Day1] Ruby on Rails练习- MacOS安装篇
查看>>
TJOI2015 旅游
查看>>
监听器实现案例----自定义session扫描器和统计在线用户人数及用户信息
查看>>
多继承
查看>>
.net4 DataAnnotations小试(转帖)
查看>>
怎么看性能瓶颈?
查看>>
解决淘淘商城“拦截器处理请求”的一个错误
查看>>
【javascript基础】1、基本概念
查看>>
IE setAttribute frameborder 相关
查看>>