使用OPCAutomation實現對opc數據的訪問

最近項目中須要 C#經過OPC方式獲取數據,折騰了一段時間,第三方提供OPCServer虛擬環境,我建立C#客戶端。json

服務端是力控電子系統,第三方軟件,很少作贅述,本文主要講解OPC客戶端的搭建和OPC鏈接步驟。數組

調用OPCAutomation類訪問OPCServer端,並進行可控制讀取間隔的OPC數據讀取、存儲工做。服務器

本文主要介紹OPCAutomation類的使用。dom

簡單流程以下:異步

1.建立OPC server的鏈接ui

2.建立OPC組對象並初始化設置this

3.獲取組的OPCItems對象,爲讀取數據作準備.net

4.opcltem的操做設計

5.退出程序的資源釋放code

 

建立鏈接很簡單,須要指定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<string, string> tagValueMap = new Dictionary<string, string>();
                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 字典,暫不作贅述,待下回分解。

關於C# dictionary字典

//goup添加items
        string[] sensorIdArray;
        void  AddGroupItems()
        {
        	List<string> l_str = new List<string>();
        	//讀取配置文件,獲取須要的傳感器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<OPCItem> ItemsAdded = new List<OPCItem>();
            int n = 0;
            MAP_CLIENTHANDLE_TAG = new Dictionary<string, string>();
            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

這段代碼設計爲了獲取到所有的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<string, string> 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 "";
        }

 

江疏影講Jav@目錄

相關文章
相關標籤/搜索