OPC client学习 2017.5.18

本文介绍了如何使用WebSocketSharp库实现WebSocket通信,并展示了通过OPC技术读取和写入工业设备数据的过程。文中详细说明了客户端与服务器端的交互流程及OPC客户端的配置步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Websocket的使用

使用WebSocketSharp.dll文件

String url = "ws://127.0.0.1:9991/api/v1/devices/rfid";

var ws = new WebSocket(url);

ws.onMessage += (sender, e) => 

Console.WriteLine("received message:" + e.Data);//接受消息

ws.Connect();ws.Send("{\"id\":\"Device-01\",\"cmd\":\"connect\",\"data\":{},\"uuid\":\"1\"}");

ws.Send("{\"id\":\"Device-01\",\"cmd\":\"ping\",\"data\":{},\"uuid\":\"2\"}");
ws.Send("{\"id\":\"Device-01\",\"cmd\":\"rfid_report\",\"data\":{\"id\":\"Device-01\"},\"uuid\":\"3\"}");
ws.Send("{\"id\":\"Device-01\",\"cmd\":\"test_rfid_open\",\"data\":{\"id\":\"Device-01\"},\"uuid\":\"4\"}");
ws.Send("{\"id\":\"Device-01\",\"cmd\":\"test_rfid_clear\",\"data\":{\"id\":\"Device-01\"},\"uuid\":\"5\"}");
 ws.Send("{\"id\":\"Device-01\",\"cmd\":\"test_rfid_close\",\"data\":{\"id\":\"Device-01\"},\"uuid\":\"6\"}");
 Console.ReadKey();


2.服务器端的WebSocket服务会将客户端发送过去的消息包装成WebsocketSessionMsg类型的数据,服务器端的Actor接受到合法的消息时会判断,做出相应的响应

客户端和服务器端可能会建立多个Session,所以服务器端可能只会遍历其中的一条Session,避免出现过多的重复消息,但是目前无法判断消息的准确性,等添加了Token之后就可以解决这个问题。


3.OPC Client    首先创建OPCServer-->>>OPCGroups---->>>OPCGroup---->>>OPCItems---->>>OPCItems的句柄

可以通过MatrikonOPC来虚拟一个OPCServer进行数据仿真。

代码:

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


namespace OpcClient
{
    class ConnectOpc
    {
        //private LoggerManagerUtil log = new LoggerManagerUtil();
        public BuhlerData buhlerData { get; set; } //布勒设备的工作状态 false表示秤上没有东西,true表示有
        public Boolean connectOpcState { get; set; } = false;//OPC服务器是否连接成功的标志位
        public ConnectServer cs { get; set; }
        private OPCServer objServer;//OPCServer类
        private OPCGroups objGroups;//通过OPCServer创建OPCGroups组
        private OPCGroup objGroup;//
        private OPCItems objItems;
        private Array strItemIDs;//Items的数组形式,2个Item上的话,需要创建3个空间,使用后边2个
        private Array lClientHandles;//客户端句柄,通过Items创建,2个Item上的话,值为0,1,2,一般使用1和2
        private Array lserverhandles;//OPC服务器端句柄,添加OPC标签Items后通过OPC服务器端赋值
        private Array lErrors;//添加OPC标签Items时OPC服务器端返回的错误信息
        //  int ltransID_Rd = 1;
        // int lCancelID_Rd;
        private object RequestedDataTypes = null;
        private object AccessPaths = null;
        //   Array lerrors_Rd;
        private Array lErrors_Wt;
        private int lTransID_Wt = 2;
        private int lCancelID_Wt;




        public void ConnectOpcMethod() {
            try {
                //(1)创建opc server对象
                objServer = new OPCServer();
                //连接opc server
                objServer.Connect("Matrikon.OPC.Simulation.1", null);
                //objServer.Connect("OPCServer.WinCC.1", null);            
                //(2)建立一个opc组集合
                objGroups = objServer.OPCGroups;
                int a = objServer.ServerState;
                //(3)建立一个opc组
                objGroup = objGroups.Add(null); //Group组名字可有可无
                //(4)添加opc标签
                objGroup.IsActive = true; //设置该组为活动状态,连接PLC时,设置为非活动状态也一样
                objGroup.IsSubscribed = true; //设置异步通知
                objGroup.UpdateRate = 200;
                objServer.OPCGroups.DefaultGroupDeadband = 0;
                objGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
                //objGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(AsyncReadComplete);
                //objGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(AsyncWriteComplete);
                objItems = objGroup.OPCItems; //建立opc标签集合
                string[] tmpIDs = new string[49];
                int[] tmpCHandles = new int[49]; 
                for (int i = 1; i < 49; i++)
                {
                    tmpCHandles[i] = i;
                }
                //tmpIDs[1] = "Random.Boolean";
                //tmpIDs[2] = "Random.Boolean";
                //tmpIDs[3] = "Triangle Waves.Int4";
initialTmpId(tmpIDs);
                strItemIDs = (Array)tmpIDs;//必须转成Array型,否则不能调用AddItems方法
                lClientHandles = (Array)tmpCHandles;
                // 添加opc标签
                objItems.AddItems(49, ref strItemIDs, ref lClientHandles, out lserverhandles, out lErrors, RequestedDataTypes, AccessPaths);
                connectOpcState = true;
            }
            catch (Exception e) {
                //log.LogManage("连接OPC异常,原因:" + e.Message);
            }




        }


        public void initialTmpId(String[] tmpId) {
            //OPC启动标志
            tmpId[1] = "PL1.Bz_PLRUN1";
            //包装信息
            tmpId[2] = "TotalBags";
            //秤清空标志
            tmpId[3] = "PL1.Gross11";
            tmpId[4] = "PL1.Gross12";
            tmpId[5] = "PL1.Gross13";
            tmpId[6] = "PL1.Gross14";
            //混合机信息
            tmpId[7] = "521_HHJ_HZ"; //混合机频率
            tmpId[8] = "mixer1.T_DSV"; //混合机设定的混合所需总时间
            tmpId[9] = "mixer1.T_FSV"; //混合机设定的放料所需总时间


            //料仓开关信号
            tmpId[10] = "IB16";
            tmpId[11] = "IB17";
            tmpId[12] = "IB18";


            //料仓名称
            tmpId[13] = "Binlm.1";
            tmpId[14] = "Binlm.2";
            tmpId[15] = "Binlm.3";
            tmpId[16] = "Binlm.4";
            tmpId[17] = "Binlm.5";
            tmpId[18] = "Binlm.6";
            tmpId[19] = "Binlm.7";
            tmpId[20] = "Binlm.8";
            tmpId[21] = "Binlm.9";
            tmpId[22] = "Binlm.10";
            tmpId[23] = "Binlm.11";
            tmpId[24] = "Binlm.12";
            tmpId[25] = "Binlm.13";
            tmpId[26] = "Binlm.14";
            tmpId[27] = "Binlm.15";
            tmpId[28] = "Binlm.16";
            tmpId[29] = "Binlm.17";
            tmpId[30] = "Binlm.18";


            //料仓余量
            tmpId[31] = "BinWeight.1";
            tmpId[32] = "BinWeight.2";
            tmpId[33] = "BinWeight.3";
            tmpId[34] = "BinWeight.4";
            tmpId[35] = "BinWeight.5";
            tmpId[36] = "BinWeight.6";
            tmpId[37] = "BinWeight.7";
            tmpId[38] = "BinWeight.8";
            tmpId[39] = "BinWeight.9";
            tmpId[40] = "BinWeight.10";
            tmpId[41] = "BinWeight.11";
            tmpId[42] = "BinWeight.12";
            tmpId[43] = "BinWeight.13";
            tmpId[44] = "BinWeight.14";
            tmpId[45] = "BinWeight.15";
            tmpId[46] = "BinWeight.16";
            tmpId[47] = "BinWeight.17";
            tmpId[48] = "BinWeight.18";


        }


        //同步写
        public void Write_Syn(String str)
        {
            try {
                if (!connectOpcState) {
                    ConnectOpcMethod();
                }
                int NumItems = 1;
                int[] Handles = new int[2];
                Handles[1] = Convert.ToInt32(lserverhandles.GetValue(3));
                Array ServerHandles = (Array)(Handles);
                object[] data = new object[2];
                //data[1] = (object)Write1.Text;
                data[1] = (object)str;
                Array Values = (Array)data;
                Array Errors;
                objGroup.SyncWrite(NumItems, ref ServerHandles, ref Values, out Errors);
            }
            catch (Exception ex) {
                //log.LogManage("向OPC写入数据异常,原因:" + ex.Message);
                DisConnect();
            }
        }


        //异步写完成
        //private void AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
        //{
        //    throw new NotImplementedException();
        //}


        //订阅方式读
        private void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            try {
                //为了测试,所以加了控制台的输出,来查看事物ID号
                //Console.WriteLine("********"+TransactionID.ToString()+"*********");


                //订阅方式读,读到的数据通过ConnectServer的Send方法发送给Java服务器
                for (int i = 0; i < NumItems; i++)
                {




                    if (Convert.ToInt32(ClientHandles.GetValue(i + 1)) == 1)
                    {
                        if (ItemValues.GetValue(i + 1) != null)
                        {
                            //this.Value1.Text = ItemValues.GetValue(i + 1).ToString();
                            //this.Quality1.Text = Qualities.GetValue(i + 1).ToString();
                            //this.TimeStamp1.Text = TimeStamps.GetValue(i + 1).ToString();
                            //ConnectBean cb = new ConnectBean("1","test_read","",2);
                            //cs.send(Bean2JsonUtil.Bean2JsonMethod(cb));
                            String Value= ItemValues.GetValue(i + 1).ToString();
                            String Quality = Qualities.GetValue(i + 1).ToString();
                            String TimeStamp = TimeStamps.GetValue(i + 1).ToString();
                            String msg = OpcDataDealUtil.OpcDataDealMethod(Value,Quality,TimeStamp);
                            cs.send(msg);
                        }
                    }
                    if (Convert.ToInt32(ClientHandles.GetValue(i + 1)) == 2)
                    {
                        if (ItemValues.GetValue(i + 1) != null)
                        {
                            //this.Value2.Text = ItemValues.GetValue(i + 1).ToString();
                            //this.Quality2.Text = Qualities.GetValue(i + 1).ToString();
                            //this.TimeStamp2.Text = TimeStamps.GetValue(i + 1).ToString();
                            //ConnectBean cb = new ConnectBean("1", "test_read", "", 2);
                            //cs.send(Bean2JsonUtil.Bean2JsonMethod(cb));
                            String Value = ItemValues.GetValue(i + 1).ToString();
                            String Quality = Qualities.GetValue(i + 1).ToString();
                            String TimeStamp = TimeStamps.GetValue(i + 1).ToString();
                            String msg = OpcDataDealUtil.OpcDataDealMethod(Value, Quality, TimeStamp);
                            cs.send(msg);
                        }
                    }
                    if (Convert.ToInt32(ClientHandles.GetValue(i + 1)) == 3)
                    {
                        if (ItemValues.GetValue(i + 1) != null)
                        {
                            //this.Value3.Text = ItemValues.GetValue(i + 1).ToString();
                            //this.Quality3.Text = Qualities.GetValue(i + 1).ToString();
                            //this.TimeStamp3.Text = TimeStamps.GetValue(i + 1).ToString();
                            //ConnectBean cb = new ConnectBean("1", "test_read", "", 2);
                            //cs.send(Bean2JsonUtil.Bean2JsonMethod(cb));
                            String Value = ItemValues.GetValue(i + 1).ToString();
                            String Quality = Qualities.GetValue(i + 1).ToString();
                            String TimeStamp = TimeStamps.GetValue(i + 1).ToString();
                            String msg = OpcDataDealUtil.OpcDataDealMethod(Value, Quality, TimeStamp);
                            cs.send(msg);
                        }
                    }
                }
            }
            catch (Exception e) {
                //log.LogManage("订阅数据异常,原因:" + e.Message);
                DisConnect();
            }
        }


        //关闭OPC连接
        private void DisConnect()
        {
            try {
                if (objServer != null)
                {
                    objServer.Disconnect();               
                }
                connectOpcState = false;
                //关闭kepserver进程,这个跟OPC操作无关
                /*
                foreach ( Process oneProcess in Process.GetProcesses())
                {
                if (oneProcess.ProcessName == "ServerMain")
                oneProcess.Kill();
                }
                */
            }
            catch (Exception  ex) {
                //log.LogManage("关闭OPC连接异常,原因:" + ex.Message);
                connectOpcState = false;
            }
        }
    }
}





opc.ua.client.dll是一个与OPC UA服务器进行通信的接口。OPC UA(OPC Unified Architecture)是一种用于工业自动化和数据交换的开放标准。它提供了一种统一的通信和数据模型,使得不同生产厂家的设备和系统可以相互通信和交换数据。 opc.ua.client.dll作为客户端接口,允许应用程序通过OPC UA协议与远程OPC UA服务器建立连接,并访问其提供的数据和功能。这个接口通过封装了底层的网络通信协议和数据处理细节,使得开发者可以更方便地使用OPC UA功能。 使用opc.ua.client.dll接口,开发者可以实现以下功能: 1. 连接到OPC UA服务器:通过接口提供的方法,可以建立到远程OPC UA服务器的连接。这样,应用程序就可以获取服务器上的数据并进行操作。 2. 浏览和读取数据节点:接口提供了获取服务器上的数据节点列表,并读取这些节点的值的方法。开发者可以通过这些方法来获取需要的数据。 3. 入数据节点:开发者可以使用接口提供的方法将数据OPC UA服务器上的数据节点。这样,可以实现对服务器上数据的控制和修改。 4. 订阅和发布数据变化:通过使用接口提供的订阅和发布机制,可以实现对数据变化的实时监听。这样,当服务器上的数据发生变化时,客户端可以及时收到通知。 总之,opc.ua.client.dll接口为开发者提供了使用OPC UA协议与OPC UA服务器进行通信的便捷方式,并支持实现与服务器之间的数据交互和控制操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值