雲平臺製做(1)-OPC Client取數模塊的製做

近來因爲工程須要,基於OPC DA 2.0搭建通用的取數模塊,與遠程webscoket服務端鏈接,並傳輸數據。在網上找了些資料,修改相應網友公開的源代碼,基本達到要求,特供你們參考。前端

1.實體類web

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OPC_DEMO
{
   public class MyOPCItem
    {
        public string key{ get; set; }
        public string Value { get; set; }
    }
}

2.源代碼json

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OPCAutomation;
using System.Threading;
using System.IO;
using WebSocketSharp;
using Newtonsoft.Json;

namespace OPC_DEMO
{
    public partial class Form1 : Form
    {
     private OPCServer KepServer;
        private OPCGroups KepGroups;
        private OPCGroup KepGroup;
        private OPCItems KepItems;
        public WebSocket wsc;
        private string JsonStr;
         private MyOPCItem opc;
        Dictionary<string, string> MAP_CLIENTHANDLE_TAG;
        public OPCItem[] OPC_ITEMS_ADDED { get; private set; }

        public Form1()
        {
            InitializeComponent();
        }

        #region OPC Client
        /// <summary>
        /// 自動鏈接OPC Server,並websocket鏈接服務器。
        /// </summary>
        private void KepServerLoad()
        {
            try
            {
                
                KepServer = new OPCServer();
                //KepServer.Connect("FBoxOpcServer", "127.0.0.1");
                KepServer.Connect("Kepware.KEPServerEx.V6","127.0.0.1");
                // KepServer.Connect("Kepware.KEPServerEx.V5","127.0.0.1");
                if (KepServer.ServerState == (int)OPCServerState.OPCRunning)
                {
                    wsc = new WebSocket("ws://10.0.0.128:6690/WsServices");
                    wsc.Connect();
                   
                    richTextBox1.Text = "OPC Server鏈接成功";
                }
                else
                {
                    richTextBox1.Text = "OPC Server鏈接失敗";
                    return;
                }
            }
            catch (Exception ex)
            {

                richTextBox1.Text = "OPC Server鏈接失敗," + ex.Message;
                return;
            }

            KepGroups = KepServer.OPCGroups;
            Thread t1; // 開1個線程用於讀取數據                 
            t1 = new Thread(new ThreadStart(KepProcess));
            t1.Start();

        }
        /// <summary>
        /// 新建OPC Group並設置相應的屬性,和觸發改變事件
        /// </summary>
        public void KepProcess()
        {
            //KepGroup = KepGroups.Add("Channel.Device.Group");
            KepGroup = KepGroups.Add("Channel1.Device1.Group");
            KepGroup.UpdateRate = 1000;
            KepGroup.IsActive = true;
            KepGroup.IsSubscribed = true;
            KepItems = KepGroup.OPCItems;
            AddGroupItems();
            //當KepGroup中數據發生改變的觸發事件    
            KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
            
           
            //    //item1 = KepItems.AddItem("My FBox.外泵站1.AI.流量1", 1);
            //    item1 = KepItems.AddItem("通道 1.設備 1.標記 1", 1);
            ////item2 = KepItems.AddItem("My FBox.外泵站1.DI.格柵運行", 2);
            //item2 = KepItems.AddItem("通道 1.設備 1.標記 2", 2);
            //item3 = KepItems.AddItem("通道 1.設備 1.test",3);
        }
        /// <summary>
        /// 單獨設立添加OPCItem方法,用來添加OPCItem
        /// </summary>
        public void AddGroupItems()
        {
            List<string> str = new List<string>();

            str.Add("通道 1.設備 1.標記 1");
            str.Add("通道 1.設備 1.標記 2");
            str.Add("通道 1.設備 1.test");

            List<OPCItem> ItemsAdd = new List<OPCItem>();
            MAP_CLIENTHANDLE_TAG = new Dictionary<string, string>();
            int n = 0;
            foreach (string tag in str)
            {
                ItemsAdd.Add(KepItems.AddItem(tag, n));
                MAP_CLIENTHANDLE_TAG.Add(n + "", tag);
                n++;
            }

            OPC_ITEMS_ADDED = ItemsAdd.ToArray();
        }


        //當數據改變時觸發的事件 
        //public delegate void DelegateShowMessage(string str);
        public delegate void DelegateShowMessage(MyOPCItem str);
        /// <summary>
        /// 數據改變事件觸發編寫,調用委託事件遠程發送。
        /// </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>
        public void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            Dictionary<string, string> tagValueMap = new Dictionary<string, string>();
            string str = "";
            // DelegateShowMessage show1 = new DelegateShowMessage(ShowMessage);
            DelegateShowMessage show1 = new DelegateShowMessage(ShowMessage);
            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);
               

                //for (int i = 1; i <= NumItems; i++)
                //{
                //    if (ClientHandles.GetValue(i).Equals(1))
                //    {
                //        str = "通道 1.設備 1.標記 1:" + ItemValues.GetValue(i).ToString();
                //    }

                //    if (ClientHandles.GetValue(i).Equals(2))
                //    {
                //        str = "通道 1.設備 1.標記 2:" + ItemValues.GetValue(i).ToString();
                //    }

                //    if (ClientHandles.GetValue(i).Equals(3))
                //    {
                //        str = "通道 1.設備 1.test:" + ItemValues.GetValue(i).ToString();

                //    }
            }
            //str = tagValueMap["通道 1.設備 1.標記 1"];
            // str = tagValueMap["通道 1.設備 1.標記 2"];
            //str = tagValueMap["通道 1.設備 1.標記 test"];
            // BeginInvoke(show1, new string[] { str });
            MyOPCItem json =ParseOPCData(tagValueMap);
            BeginInvoke(show1, json);


        }
        //public string ParseOPCData(Dictionary<string,string> tagValueMap)
        //{
        //    foreach (var item in tagValueMap)
        //    {
        //        string key = item.Key;
        //        var value = item.Value;
        //        return "{"+"key:"+ key + "," + "Value:"+ value+"}";
        //    }
        //    return "";
        //}
        /// <summary>
        /// 讀Dictionary中的值,並傳遞給實體類。
        /// </summary>
        /// <param name="tagValueMap"></param>
        /// <returns></returns>
        public MyOPCItem ParseOPCData(Dictionary<string, string> tagValueMap)
        {
            opc = new MyOPCItem();
            foreach (var item in tagValueMap)
            {
                opc.key = item.Key;
                opc.Value = item.Value;
                return opc;
            }
            return null;
        }
        //public void ShowMessage(string str)
        //{
        //    //wsc.Send(JsonConvert.SerializeObject(str));
        //    // wsc.Send(str);
         
        //    richTextBox1.AppendText(str + System.Environment.NewLine);
          
        //}
        /// <summary>
        /// websocket傳遞數據,和測試客戶端顯示。
        /// </summary>
        /// <param name="opc"></param>
            public void ShowMessage(MyOPCItem opc)
        {
            wsc.Send(JsonConvert.SerializeObject(opc));
            richTextBox1.AppendText(opc.Value + System.Environment.NewLine);
        }

        #endregion
        private void Form1_Load_1(object sender, EventArgs e)
        {
            KepServerLoad();
        }

        private void Form1_FormClosing_1(object sender, FormClosingEventArgs e)
        {
             KepServer.Disconnect();
        }

       

    }
}

3.結論性能優化

 初步實現與websocket的數據對接,以json對象的形式傳遞,還須要websocket服務端將其反序列化爲json字符串,並解析給前端使用。固然,這只是一個初步的Demo,其性能優化,線程佔有的內存,以及穩定性都有待測試。服務器

相關文章
相關標籤/搜索