从头开始实施OPC DA客户端

时间:2013-07-24 15:06:30

标签: opc

我想从头开始实现自己的OPC DA客户端(版本2.02,2.05a,3.00),但不使用任何第三方。另外,我想利用OPCEnum.exe服务获取已安装的OPC服务器列表。是否有任何类型的文档详细解释了实施OPC客户端的过程?

1 个答案:

答案 0 :(得分:4)

我有一个c#实现,但实际上很难适应它。我将尝试总结所需的步骤。

大多数情况下,您需要从Opcfoundation.org免费下载OPC Core Components Redistributable软件包中的OpcRcw.Comn.dll和OpcRcw.Da.dll。安装后,文件位于C:\ Windows \ assembly \ GAC_MSIL中。在项目中创建一个引用。

关于编码,这是你应该做的(你想要实现三个对象,服务器,组和项目):

让我们从服务器开始:

 Type typeofOPCserver = Type.GetTypeFromProgID(serverName, computerName, true);
 m_opcServer = (IOPCServer)Activator.CreateInstance(typeofOPCserver);
 m_opcCommon = (IOPCCommon)m_opcServer;
 IConnectionPointContainer icpc = (IConnectionPointContainer)m_opcServer;
 Guid sinkGUID = typeof(IOPCShutdown).GUID;
 icpc.FindConnectionPoint(ref sinkGUID, out m_OPCCP);
 m_OPCCP.Advise(this, out m_cookie_CP);

我已经在这里划了很多检查以适应它,把它当作样本...... 然后,您需要在服务器上添加组的方法:

 // Parameter as following:
 // [in] active, so do OnDataChange callback
 // [in] Request this Update Rate from Server
 // [in] Client Handle, not necessary in this sample
 // [in] No time interval to system UTC time
 // [in] No Deadband, so all data changes are reported
 // [in] Server uses english language to for text values
 // [out] Server handle to identify this group in later calls
 // [out] The answer from Server to the requested Update Rate
 // [in] requested interface type of the group object
 // [out] pointer to the requested interface
 m_opcServer.AddGroup(m_groupName, Convert.ToInt32(m_isActive), m_reqUpdateRate, m_clientHandle, pTimeBias, pDeadband, m_LocaleID, out m_serverHandle, out m_revUpdateRate, ref iid, out objGroup); 

 // Get our reference from the created group
 m_OPCGroupStateMgt = (IOPCGroupStateMgt)objGroup;

最后你需要创建项目:

 m_OPCItem = (IOPCItemMgt)m_OPCGroupStateMgt;
 m_OPCItem.AddItems(itemList.Length, GetAllItemDefs(itemList), out ppResults, out ppErrors);

其中itemlist是OPCITEMDEF []的数组。我使用来自我的结构的GetAllItemDefs来构建上述内容。

    private static OPCITEMDEF[] GetAllItemDefs(params OpcItem[] opcItemList)
    {
        OPCITEMDEF[] opcItemDefs = new OPCITEMDEF[opcItemList.Length];
        for (int i = 0; i < opcItemList.Length; i++)
        {
            OpcItem opcItem = opcItemList[i];
            opcItemDefs[i].szAccessPath = "";
            opcItemDefs[i].bActive = Convert.ToInt32(opcItem.IsActive);
            opcItemDefs[i].vtRequestedDataType = Convert.ToInt16(opcItem.ItemType, CultureInfo.InvariantCulture);
            opcItemDefs[i].dwBlobSize = 0;
            opcItemDefs[i].pBlob = IntPtr.Zero;
            opcItemDefs[i].hClient = opcItem.ClientHandle;
            opcItemDefs[i].szItemID = opcItem.Id;
        }
        return opcItemDefs;
    }

最后,关于枚举服务器,我使用这两个函数:

   /// <summary>
    /// Enumerates hosts that may be accessed for server discovery.
    /// </summary>
    [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
    public string[] EnumerateHosts()
    {
        IntPtr pInfo;

        int entriesRead = 0;
        int totalEntries = 0;

        int result = NetServerEnum(
            IntPtr.Zero,
            LEVEL_SERVER_INFO_100,
            out pInfo,
            MAX_PREFERRED_LENGTH,
            out entriesRead,
            out totalEntries,
            SV_TYPE_WORKSTATION | SV_TYPE_SERVER,
            IntPtr.Zero,
            IntPtr.Zero);

        if (result != 0)
            throw new ApplicationException("NetApi Error = " + String.Format("0x{0,0:X}", result));

        string[] computers = new string[entriesRead];

        IntPtr pos = pInfo;
        for (int ii = 0; ii < entriesRead; ii++)
        {
            SERVER_INFO_100 info = (SERVER_INFO_100)Marshal.PtrToStructure(pos, typeof(SERVER_INFO_100));
            computers[ii] = info.sv100_name;
            pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(SERVER_INFO_100)));
        }

        NetApiBufferFree(pInfo);
        return computers;
    }

    /// <summary>
    /// Returns a list of servers that support the specified specification on the specified host.
    /// </summary>
    [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
    public string[] GetAvailableServers(Specification specification)
    {
        lock (this)
        {
            // connect to the server.
            ArrayList servers = new ArrayList();
            MULTI_QI[] results = new MULTI_QI[1];
            GCHandle hIID = GCHandle.Alloc(IID_IUnknown, GCHandleType.Pinned);

            results[0].iid = hIID.AddrOfPinnedObject();
            results[0].pItf = null;
            results[0].hr = 0;

            try
            {
                // create an instance.
                Guid srvid = CLSID;
                CoCreateInstanceEx(srvid, null, CLSCTX.CLSCTX_LOCAL_SERVER, IntPtr.Zero, 1, results);

                m_server = (IOPCServerList2)results[0].pItf;

                // convert the interface version to a guid.
                Guid catid = new Guid(specification.ID);

                // get list of servers in the specified specification.
                IOPCEnumGUID enumerator = null;
                m_server.EnumClassesOfCategories(1, new Guid[] { catid }, 0, null, out enumerator);

                // read clsids.
                Guid[] clsids = ReadClasses(enumerator);

                // release enumerator
                if (enumerator != null && enumerator.GetType().IsCOMObject)
                    Marshal.ReleaseComObject(enumerator);

                // fetch class descriptions.
                foreach (Guid clsid in clsids)
                {
                    try
                    {
                        string url = CreateUrl(specification, clsid);
                        servers.Add(url);
                    }
                    catch (Exception) { }
                }
            }
            catch
            {
            }
            finally
            {
                if (hIID.IsAllocated) hIID.Free();
                if (m_server != null && m_server.GetType().IsCOMObject)
                    Marshal.ReleaseComObject(m_server);
            }
            return (string[])servers.ToArray(typeof(string));
        }
    }

我知道我已经划了很多但也许它仍然可以帮助你;) 如果您认为我已经清楚了,请将答案标记为正确;) 亲切的问候, d。