zoukankan      html  css  js  c++  java
  • 【源代码】西门子Simatic.NET与Visual C#异步通讯的代码

    /*********************************************************************
     * 模块名称:OPC服务器类
     * 版    本:Version 0.97a
     * 作    者:龙少爷
     * 时    间:2010-11-16 11:43
     * 备    注: 
     *      OPC服务器的常用操作:连接,断开,读,写,设置状态
     * 附    注:
     *            
     * *******************************************************************/
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.Runtime.InteropServices;
    
    using OpcRcw.Da;
    using OpcRcw.Comn;
    
    namespace Utility.PLC
    {
        /// <summary>
        /// OPC服务器类 By 龙少爷 2010
        /// </summary>
        public class OPCServer
        {
            #region OPCServer Common Fields
            private OpcRcw.Da.IOPCServer ServerObj;//OPCServer  
    
            private OpcRcw.Da.IOPCAsyncIO2 IOPCAsyncIO2Obj = null;//异步读写对象  
            private OpcRcw.Da.IOPCGroupStateMgt IOPCGroupStateMgtObj = null;//组管理对象  
    
            private IConnectionPointContainer pIConnectionPointContainer = null;
            private IConnectionPoint pIConnectionPoint = null;
    
            public const int LOCALE_ID = 0x407;
    
            private Object MyobjGroup1 = null;
            private int[] ItemServerHandle;
            private int pSvrGroupHandle = 0;
            private Int32 dwCookie = 0;
    
            #endregion
    
            #region OPCServer User-Defined Variables
            #endregion
    
            #region OPCServer Constructors
            public OPCServer()
            {
    
            }
            #endregion
    
            #region Methods
    
            /// <summary>
            /// 建立PC到PLC的连接,返回OPC服务器对象
            /// </summary>
            /// <param name="programID">将要连接的进程ID</param>
            /// <param name="server">服务器IP地址</param>
            /// <returns>OPC服务器对象</returns>
            public bool CreateServer(string programID, string server)
            {
                Type svrComponenttyp;
                try
                {
                    svrComponenttyp = Type.GetTypeFromProgID(programID, server);//OPCServer  
                    ServerObj = (IOPCServer)Activator.CreateInstance(svrComponenttyp);//注册  
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
    
            /// <summary>
            /// 添加一个组对象,并返回该组对象的引用
            /// </summary>
            /// <param name="form">回调对象</param>
            /// <returns>是否执行成功</returns>
            public bool AddGroup(object form)
            {
                Int32 dwRequestedUpdateRate = 1000;
                Int32 hClientGroup = 1;
                Int32 pRevUpdateRate;
    
                float deadband = 0;
    
                int TimeBias = 0;
                GCHandle hTimeBias, hDeadband;
                hTimeBias = GCHandle.Alloc(TimeBias, GCHandleType.Pinned);
                hDeadband = GCHandle.Alloc(deadband, GCHandleType.Pinned);
                Guid iidRequiredInterface = typeof(IOPCItemMgt).GUID;
    
                try
                {
                    ServerObj.AddGroup("MyOPCGroup1",//组对象  
                        0,
                        dwRequestedUpdateRate,
                        hClientGroup,
                        hTimeBias.AddrOfPinnedObject(),
                        hDeadband.AddrOfPinnedObject(),
                        LOCALE_ID,
                        out pSvrGroupHandle,
                        out pRevUpdateRate,
                        ref iidRequiredInterface,
                        out MyobjGroup1);
    
                    IOPCAsyncIO2Obj = (IOPCAsyncIO2)MyobjGroup1;
                    //Query interface for Async calls on group object  
    
                    IOPCGroupStateMgtObj = (IOPCGroupStateMgt)MyobjGroup1;
    
                    pIConnectionPointContainer = (IConnectionPointContainer)MyobjGroup1;
                    //定义特定组的异步调用连接  
    
                    Guid iid = typeof(IOPCDataCallback).GUID;
                    // Establish Callback for all async operations  
                    pIConnectionPointContainer.FindConnectionPoint(ref iid, out pIConnectionPoint);
    
                    // Creates a connection between the OPC servers's connection point and this client's sink (the callback object)  
                    pIConnectionPoint.Advise(form, out dwCookie);
    
                    return true;
                }
                catch (Exception ex)// catch for group adding  
                {
                    return false;
                }
                finally
                {
                    if (hDeadband.IsAllocated)
                        hDeadband.Free();
                    if (hTimeBias.IsAllocated)
                        hTimeBias.Free();
                }
            }
            /// <summary>
            /// 添加一个读写的Items数组对象
            /// Ex:
            ///     OpcRcw.Da.OPCITEMDEF[] ItemArray = new OPCITEMDEF[3];//  
            ///     ItemArray[0].szAccessPath = "";
            ///     ItemArray[0].szItemID = "S7:[S7 connection_1]DB13,DWORD0";
            ///     //地址,不同数据类型表示方法不同  
            ///     ItemArray[0].bActive = 1;//是否激活  
            ///     ItemArray[0].hClient = 1;//表示ID  
            ///     ItemArray[0].dwBlobSize = 0;
            ///     ItemArray[0].pBlob = IntPtr.Zero;
            ///     ItemArray[0].vtRequestedDataType = 2;
            /// </summary>
            /// <param name="items">Items读写对象数组</param>
            /// <returns>Items是否执行成功</returns>
            public bool AddItems(OPCITEMDEF[] items)
            {
                IntPtr pResults = IntPtr.Zero;
                IntPtr pErrors = IntPtr.Zero;
    
                try
                {
                    ((IOPCItemMgt)MyobjGroup1).AddItems(items.Length, items, out  pResults, out pErrors);
    
                    int[] errors = new int[items.Length];
                    Marshal.Copy(pErrors, errors, 0, items.Length);
    
                    ItemServerHandle = new int[items.Length];
    
                    IntPtr pos = pResults;
    
                    OPCITEMRESULT result;
    
                    if (errors[0] == 0)
                    {
                        result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT));
                        ItemServerHandle[0] = result.hServer;
                    }
                    for (int i = 1; i < errors.Length; i++)
                    {
                        if (errors[i] == 0)
                        {
                            pos = new IntPtr(pos.ToInt32() + Marshal.SizeOf(typeof(OPCITEMRESULT)));
                            result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT));
                            ItemServerHandle[i] = result.hServer;
                        }
                    }
                    return true;
                }
                catch (Exception ex) // catch for add item  
                {
                    return false;
                }
                finally
                {
                    // Free the memory  
                    if (pResults != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(pResults);
                        pResults = IntPtr.Zero;
                    }
                    if (pErrors != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(pErrors);
                        pErrors = IntPtr.Zero;
                    }
                }
            }
            /// <summary>
            /// 发送异步读命令,结果的读取要通过实现IOPCDataCallback接口的OnReadComplete函数实现
            /// </summary>
            /// <param name="itemServerHandles">Item读写对象句柄数组</param>
            /// <returns>是否执行成功</returns>
            public bool Read()
            {
                int nCancelid;
                IntPtr pErrors = IntPtr.Zero;
                if (IOPCAsyncIO2Obj != null)
                {
                    try
                    {
                        IOPCAsyncIO2Obj.Read(ItemServerHandle.Length, ItemServerHandle, ItemServerHandle.Length, out nCancelid, out pErrors);
                        int[] errors = new int[ItemServerHandle.Length];
                        Marshal.Copy(pErrors, errors, 0, ItemServerHandle.Length);
                        return false;
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
                else
                    return false;
            }
            /// <summary>
            /// 发送异步写命令,结果的状态,要通过实现IOPCDataCallback接口的OnWriteComplete函数实现
            /// </summary>
            /// <param name="itemIndex">要写的Item项</param>
            /// <param name="values">要写入到PLC中的值数组</param>
            /// <returns>是否执行成功</returns>
            public bool Write(int itemIndex, object[] values)
            {
                int nCancelid;
                IntPtr pErrors = IntPtr.Zero;
    
                int[] phServer = new int[1];
                phServer[0] = itemIndex;
    
                if (IOPCAsyncIO2Obj != null)
                {
                    try
                    {
                        IOPCAsyncIO2Obj.Write(1, phServer, values, itemIndex, out nCancelid, out pErrors);
    
                        int[] errors = new int[1];
                        Marshal.Copy(pErrors, errors, 0, 1);
    
                        if (errors[0] != 0)//Error in reading item
                        {
                            Marshal.FreeCoTaskMem(pErrors);
                            pErrors = IntPtr.Zero;
                            return false;
                        }
                        return true;
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
                else
                    return false;
            }
            /// <summary>
            /// 发送异步写命令,结果的状态,要通过实现IOPCDataCallback接口的OnWriteComplete函数实现
            /// </summary>
            /// <param name="values">要写入到PLC中的值数组</param>
            /// <returns>是否执行成功</returns>
            public bool Write(object[] values)
            {
                int nCancelid;
                IntPtr pErrors = IntPtr.Zero;
    
                if (IOPCAsyncIO2Obj != null)
                {
                    try
                    {
                        IOPCAsyncIO2Obj.Write(ItemServerHandle.Length, ItemServerHandle, values, ItemServerHandle.Length, out nCancelid, out pErrors);
    
                        int[] errors = new int[ItemServerHandle.Length];
                        Marshal.Copy(pErrors, errors, 0, ItemServerHandle.Length);
    
                        bool bError = false;
                        foreach (int err in errors)//Error in reading item
                        {
                            if (err != 0)
                            {
                                bError = true;
                                break;
                            }
                        }
                        if (bError)
                        {
                            Marshal.FreeCoTaskMem(pErrors);
                            pErrors = IntPtr.Zero;
                            return false;
                        }
                        return true;
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
                else
                    return false;
            }
            /// <summary>
            /// 设置PLC状态,使之处罚OnDataChange事件函数
            /// </summary>
            /// <param name="group"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public bool SetState(bool value)
            {
                IntPtr pRequestedUpdateRate = IntPtr.Zero;
                int nRevUpdateRate = 0;
                IntPtr hClientGroup = IntPtr.Zero;
                IntPtr pTimeBias = IntPtr.Zero;
                IntPtr pDeadband = IntPtr.Zero;
                IntPtr pLCID = IntPtr.Zero;
                int nActive = 0;
    
                // activates or deactivates group according to checkbox status  
                GCHandle hActive = GCHandle.Alloc(nActive, GCHandleType.Pinned);
                if (value != true)
                    hActive.Target = 0;
                else
                    hActive.Target = 1;
                try
                {
                    IOPCGroupStateMgtObj.SetState(pRequestedUpdateRate, out nRevUpdateRate, hActive.AddrOfPinnedObject(), pTimeBias, pDeadband, pLCID, hClientGroup);
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
                finally
                {
                    hActive.Free();
                }
            }
            /// <summary>
            /// 断开PC到PLC的连接
            /// </summary>
            /// <returns>是否成功执行</returns>
            public bool DisConnect()
            {
                try
                {
                    if (dwCookie != 0)
                    {
                        pIConnectionPoint.Unadvise(dwCookie);
                        dwCookie = 0;
                    }
                    // Free unmanaged code  
                    Marshal.ReleaseComObject(pIConnectionPoint);
                    pIConnectionPoint = null;
    
                    Marshal.ReleaseComObject(pIConnectionPointContainer);
                    pIConnectionPointContainer = null;
    
                    if (IOPCAsyncIO2Obj != null)
                    {
                        Marshal.ReleaseComObject(IOPCAsyncIO2Obj);
                        IOPCAsyncIO2Obj = null;
                    }
    
                    ServerObj.RemoveGroup(pSvrGroupHandle, 0);
                    if (IOPCGroupStateMgtObj != null)
                    {
                        Marshal.ReleaseComObject(IOPCGroupStateMgtObj);
                        IOPCGroupStateMgtObj = null;
                    }
                    if (MyobjGroup1 != null)
                    {
                        Marshal.ReleaseComObject(MyobjGroup1);
                        MyobjGroup1 = null;
                    }
                    if (ServerObj != null)
                    {
                        Marshal.ReleaseComObject(ServerObj);
                        ServerObj = null;
                    }
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
    
            }
            #endregion
    
            #region  Public Properity
            public OpcRcw.Da.IOPCServer Server
            {
                get
                {
                    return this.ServerObj;
                }
            }
            #endregion
        }
    
    }
    
    

    如何使用的范例:

    由于上面的代码只是简单的封装了OPC的基本操作,然而却在项目中使用并不简洁方便,为此又写了一个接口。

    /*********************************************************************
     * 模块名称:定义在操作PLC的常用操作和属性
     * 作    者:龙少爷
     * 时    间:2010-11-24 11:44
     * 备    注:
     * 
     * 历史修改记录
     * 作    者:
     * 修改时间:
     * 备    注:
     * 
     * *******************************************************************/
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Picking
    {
        /// <summary>
        /// 定义在操作PLC的常用操作和属性
        /// </summary>
        public interface IPLCOperator
        {
            /// <summary>
            /// 数据库是否已经连接上
            /// </summary>
            bool IsConnected { get; set; }
            /// <summary>
            /// 建立PC到PLC的连接,由指定的adviser参数对象来处理事件的结果
            /// </summary>
            /// <param name="adviser">接受处理结果的对象</param>
            /// <returns>true/false</returns>
            bool ConnectToPLC(string programID, string server, object adviser);
    
            bool ReadFromPLCDB();
    
            bool WriteIntoPLCDB(object[] values);
    
            bool SetPLCState(bool state);
    
            bool DisConnectFromPLC();
    
    
        }
    }
    
    

    与PLC交互的代码,之所以这样写一个单独的类,是为了在同时读写多个ITEM项时,能把每个操作独立出来处理:

    /*********************************************************************
     * 模块名称:
     * 作    者:龙少爷
     * 时    间:2010-11-24 13:44
     * 备    注:
     * 
     * 历史修改记录
     * 作    者:
     * 修改时间:
     * 备    注:
     * 
     * *******************************************************************/
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Utility.PLC;
    
    using OpcRcw.Da;
    
    namespace Picking
    {
        /// <summary>
        /// 
        /// </summary>
        public class DLStopLine : IOPCDataCallback, IPLCOperator
        {
            #region  私有变量
            private OPCServer opcServer = null;
            #endregion
    
            #region Public Constructor
            public DLStopLine()
            {
                opcServer = new OPCServer();
            }
            #endregion
    
            #region IPLCOperator 成员
    
            public bool IsConnected
            {
                get;
                set;
            }
    
            public bool ConnectToPLC(string programID, string server, object adviser)
            {
                if (!opcServer.CreateServer(programID, server))
                {
                    IsConnected = false;
                    return false;
                }
                if (!opcServer.AddGroup(adviser))
                {
                    IsConnected = false;
                    return false;
                }
                OpcRcw.Da.OPCITEMDEF[] items = new OPCITEMDEF[1];//定义读写的item,共个变量   
                items[0].szAccessPath = "";
                items[0].szItemID = "S7:[S7 connection_1]DB20,B1";    //地址,不同数据类型表示方法不同   
                items[0].bActive = 1;//是否激活   
                items[0].hClient = 1;//表示ID   
                items[0].dwBlobSize = 0;
                items[0].pBlob = IntPtr.Zero;
                items[0].vtRequestedDataType = 17;
    
                if (!opcServer.AddItems(items))
                {
                    IsConnected = false;
                    return false;
                }
                IsConnected = true;
                return true;
            }
    
            public bool ConnectToPLC(string programID, string server)
            {
                return ConnectToPLC(programID, server, this);
            }
    
            public bool ConnectToPLC(object adviser)
            {
                return ConnectToPLC("OPC.SimaticNet", "localhost", adviser);
            }
    
            public bool ConnectToPLC()
            {
                return ConnectToPLC("OPC.SimaticNet", "localhost", this);
            }
    
            public bool ReadFromPLCDB()
            {
                return opcServer.Read();
            }
    
            public bool WriteIntoPLCDB(object[] values)
            {
                return opcServer.Write(values);
            }
    
            public bool SetPLCState(bool state)
            {
                return opcServer.SetState(state);
            }
    
            public bool DisConnectFromPLC()
            {
                return opcServer.DisConnect();
            }
    
            #endregion
    
            #region IOPCDataCallback 成员
    
            public void OnCancelComplete(int dwTransid, int hGroup)
            {
    
            }
    
            public void OnDataChange(int dwTransid, int hGroup, int hrMasterquality, int hrMastererror, int dwCount, int[] phClientItems, object[] pvValues, short[] pwQualities, FILETIME[] pftTimeStamps, int[] pErrors)
            {
    
            }
    
            public void OnReadComplete(int dwTransid, int hGroup, int hrMasterquality, int hrMastererror, int dwCount, int[] phClientItems, object[] pvValues, short[] pwQualities, FILETIME[] pftTimeStamps, int[] pErrors)
            {
    
            }
    
            public void OnWriteComplete(int dwTransid, int hGroup, int hrMastererr, int dwCount, int[] pClienthandles, int[] pErrors)
            {
    
            }
    
            #endregion
    
            #region  Destructor
            ~DLStopLine()
            {
                if (IsConnected)
                    opcServer.DisConnect();
            }
            #endregion
    
        }
    }
    
    

     在项目中,编写相应的调用代码即可。

                DLStopLine stopLine = new DLStopLine();
                stopLine.ConnectToPLC();
    
                values = new object[1];
                values[0] = 1;
                stopLine.WriteIntoPLCDB(values);
    
  • 相关阅读:
    阶段3 3.SpringMVC·_03.SpringMVC常用注解_1 RequestParam注解
    阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_7 获取Servlet原生的API
    函数传参
    利用 操作符特性 代替if判断语句
    for(;;)和 while(1) 有什么区别吗?for()和while()的使用情景。
    一个简单的mfc单页界面文件读写程序(MFC 程序入口和执行流程)
    ARM异常---一个DataAbort的触发过程:
    C语言,单链表操作(增删改查)(version 0.1)
    Cpu实验
    H-JATG:NAND_FLASH的参数设置
  • 原文地址:https://www.cnblogs.com/longshaoye/p/1890429.html
Copyright © 2011-2022 走看看