• 云平台制作(1)-OPC Client取数模块的制作


    近来由于工程需要,基于OPC DA 2.0搭建通用的取数模块,与远程webscoket服务端连接,并传输数据。在网上找了些资料,修改相应网友公开的源代码,基本达到要求,特供大家参考。

    1.实体类

    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.源代码

    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,其性能优化,线程占有的内存,以及稳定性都有待测试。

  • 相关阅读:
    SQL Server 与 Entity Framework 级联删除
    web api 2 学习笔记 (Odata ODataQueryOptions 使用)
    【建议收藏】设计师必备-史上最全的个人资料页面设计模板下载
    浅谈产品经理入门和学习路径
    最全面!2019年最新UX设计趋势预测合集
    最新Dashboard设计实例、技巧和资源集锦,视觉和功能两不误,妥妥的!
    【技巧分享】设计师如何向开发人员顺利交付作品?
    摹客iDoc201901-2新功能点评
    企业类Web原型制作分享-Kraftwerk
    【新年福利】2019年值得一用的8款协作工具
  • 原文地址:https://www.cnblogs.com/cache-yuan/p/11041678.html
Copyright © 2020-2023  润新知