OPC Winform客户端和WebSocket访问

本文介绍了两种形式访问OPC服务器,并与其进行通信。

基础环境:本地如果没有OPC环境,可以安装 KEPServerEX6.5 测试环境。

一、Winform客户端访问与OPC通信

  1. 引入Interop.OPCAutomation.dll
  2. 新建OPCHelper.cs
 
载入窗体时获取本地OPC服务器
private void MainFrom_Load(object sender, EventArgs e)
{
    GetLocalServer();
}

/// <summary>
/// 枚举本地OPC服务器
/// </summary>
private void GetLocalServer()
{
    try
    {
        var items = OPCHelper.GetLocalServer();
        foreach (string turn in items)
        {
            cmbServerName.Items.Add(turn);
        }
        if (cmbServerName.Items != null && cmbServerName.Items.Count > 0)
        {
            cmbServerName.SelectedIndex = 0;
        }
    }
    catch (Exception err)
    {
        MessageBox.Show("枚举本地OPC服务器出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }
}
3.创建OPCHelper.cs
public class OPCHelper
{
    /// <summary>
    /// 时长
    /// </summary>
    public const int JET_LAG = 8;

    #region 公共属性

    /// <summary>
    /// OPCServer Object
    /// </summary>
    public OPCServer KepServer { get; set; }

    /// <summary>
    /// OPCGroups Object
    /// </summary>
    public OPCGroups KepGroups { get; set; }

    /// <summary>
    /// OPCGroup Object
    /// </summary>
    public OPCGroup KepGroup { get; set; }

    /// <summary>
    /// OPCItems Object
    /// </summary>
    public OPCItems KepItems { get; set; }

    /// <summary>
    /// OPCItem Object
    /// </summary>
    public OPCItem KepItem { get; set; }

    /// <summary>
    /// 主机IP
    /// </summary>
    public string HostIP { get; set; }

    /// <summary>
    /// 主机名称
    /// </summary>
    public string HostName { get; set; }

    /// <summary>
    /// 连接状态
    /// </summary>
    public bool OPCConnected { get; set; }

    /// <summary>
    /// 客户端句柄
    /// </summary>
    public int ItemHandleClient { get; set; }

    /// <summary>
    /// 服务端句柄
    /// </summary>
    public int ItemHandleServer { get; set; }

    public List<string> opcItemsArray;

    public Dictionary<int, OPCItem> OPCItemDic;

    public List<OPCData> OPCDatas;

    #endregion

    public OPCHelper()
    {
        this.HostIP = string.Empty;

        this.HostName = string.Empty;

        this.OPCConnected = false;

        this.ItemHandleClient = 0;

        this.ItemHandleServer = 0;

        this.OPCDatas = new List<OPCData>();

        this.OPCItemDic = new Dictionary<int, OPCItem>();

    }

    public void Write(string value)
    {
        if (this.KepItems.Count > 0)
        {

            OPCItem bItem = this.KepItems.GetOPCItem(this.ItemHandleServer);
            int[] temp = new int[2] { 0, bItem.ServerHandle };
            Array serverHandles = (Array)temp;
            Array Errors;
            int cancelID;

            //KepGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, 2009, out cancelID);

            //KepItem.Write(Convert.ToInt32(txtWriteTagValue.Text));//这句也可以写入,但并不触发写入事件

            this.KepItem.Write(Convert.ToInt32(value));//这句也可以写入,但并不触发写入事件
            GC.Collect();
        }
    }

    public void SetDatas()
    {

        object value1;

        object quality1;

        object timeStamp1;

        var dataSourceNum = this.OPCDatas.Count();

        for (int i = 0, count = this.OPCItemDic.Keys.ToList().Count; i < count; i++)
        {
            var item = this.OPCItemDic.Values.ToList()[i];
            item.Read((short)OPCDataSource.OPCDevice, out value1, out quality1, out timeStamp1);
            OPCData data = null;
            for (int n = 0; n < dataSourceNum; n++)
            {
                if (item.ItemID == this.OPCDatas[n].ItemID)
                {
                    data = this.OPCDatas[n];
                    break;
                }
            }

            if (data == null)
            {
                this.OPCDatas.Add(new OPCData()
                {
                    ItemID = item.ItemID,

                    Value = value1 != null ? value1.ToString() : string.Empty,

                    Quanlity = quality1 != null ? quality1.ToString() : string.Empty,

                    TimeStamp = timeStamp1 != null ? Convert.ToDateTime(timeStamp1.ToString()).AddHours(JET_LAG).ToString() : string.Empty
                });
            }
            else
            {
                for (int j = 0; j < dataSourceNum; j++)
                {
                    if (this.OPCDatas[j].ItemID == data.ItemID)
                    {
                        this.OPCDatas[j].Value = value1 != null ? value1.ToString() : string.Empty;

                        this.OPCDatas[j].TimeStamp = timeStamp1 != null ? Convert.ToDateTime(timeStamp1.ToString()).AddHours(JET_LAG).ToString() : string.Empty;

                        this.OPCDatas[j].Quanlity = quality1 != null ? quality1.ToString() : string.Empty;

                        break;
                    }
                }
            }
        }
    }

    /// <summary>
    /// 枚举本地OPC服务器
    /// </summary>
    public List<string> GetLocalServer()
    {
        List<string> servers = new List<string>();
        //获取本地计算机IP,计算机名称
        IPHostEntry IPHost = Dns.Resolve(Environment.MachineName);
        if (IPHost.AddressList.Length > 0)
        {
            this.HostIP = IPHost.AddressList[0].ToString();
        }
        else
        {
            return servers;
        }

        //通过IP来获取计算机名称,可用在局域网内
        IPHostEntry ipHostEntry = Dns.GetHostByAddress(this.HostIP);
        this.HostName = ipHostEntry.HostName.ToString();
        //获取本地计算机上的OPCServerName
        try
        {
            this.KepServer = new OPCServer();
            object serverList = this.KepServer.GetOPCServers(this.HostName);
            foreach (string turn in (Array)serverList)
            {
                servers.Add(turn);
            }
        }
        catch (Exception err)
        {
            MessageBox.Show("枚举本地OPC服务器出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
        return servers;
    }
}

二、以WebSocket形式访问OPC

允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

后端实现

需要引入 Fleck

private static List<IWebSocketConnection> allSockets;

static void Main(string[] args)
{
    FleckLog.Level = LogLevel.Debug;
    var server = new WebSocketServer("ws://0.0.0.0:9999");
    allSockets = new List<IWebSocketConnection>();
    server.Start(socket =>
    {
        socket.OnOpen = () =>
        {
            Open(socket);
        };
        socket.OnClose = () =>
        {
            Console.WriteLine("Close!");
            allSockets.Remove(socket);
        };
        socket.OnMessage = message =>
        {
            ReceivingClientMessage(message);
        };
    });
    var input = Console.ReadLine();
    while (input != "exit")
    {
        foreach (var socket in allSockets.ToList())
        {
            socket.Send(input);
        }
        input = Console.ReadLine();
    }
}

#region  Socket操作
/// <summary>
/// 发送消息至客户端
/// </summary>
/// <param name="message"></param>
private static void SendMessageToClient(string message)
{
    var input = message;// Console.ReadLine();
    foreach (var socket in allSockets.ToList())
    {
        socket.Send(input);
    }
}

/// <summary>
/// 打开
/// </summary>
/// <param name="socket"></param>
private static void Open(IWebSocketConnection socket)
{
    Console.WriteLine("Open!");
    allSockets.Add(socket);
}

/// <summary>
/// 接收客户端信息
/// </summary>
/// <param name="message"></param>
static void ReceivingClientMessage(string json)
{
    allSockets.ToList().ForEach(s => s.Send("Echo: " + json));
}

#endregion

前端实现

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>websocket client</title>
    <script type="text/javascript">
        var start = function () {
            var inc = document.getElementById('incomming');
            var wsImpl = window.WebSocket || window.MozWebSocket;
            var form = document.getElementById('sendForm');
            var input = document.getElementById('sendText');

            inc.innerHTML += "connecting to server ..<br/>";

            // create a new websocket and connect
            window.ws = new wsImpl('ws://localhost:9999/');

            // when data is comming from the server, this metod is called
            ws.onmessage = function (evt) {
                inc.innerHTML += evt.data + '<br/>';
            };

            // when the connection is established, this method is called
            ws.onopen = function () {
                inc.innerHTML += '.. connection open<br/>';
            };

            // when the connection is closed, this method is called
            ws.onclose = function () {
                inc.innerHTML += '.. connection closed<br/>';
            }

            form.addEventListener('submit', function (e) {
                e.preventDefault();
                
                var val = input.value;
                ws.send(val);
                input.value = "";
            });
        }
        window.onload = start;
    </script>
</head>
<body>
    <form id="sendForm">
        <input id="sendText" placeholder="Text to send" />       
        <input type="submit" value="发送"></input>        
    </form>
    <pre id="incomming"></pre>
</body>
</html>

资源下载地址:https://download.csdn.net/download/lincongqiong819/12406289

一分辛苦一分才
原文地址:https://www.cnblogs.com/JoanLin-workNotes/p/12864013.html