OPC Winform客户端和WebSocket访问
本文介绍了两种形式访问OPC服务器,并与其进行通信。
基础环境:本地如果没有OPC环境,可以安装 KEPServerEX6.5 测试环境。
一、Winform客户端访问与OPC通信
- 引入Interop.OPCAutomation.dll
- 新建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
一分辛苦一分才