gpt4 book ai didi

opc - 从头开始实现 OPC DA 客户端

转载 作者:行者123 更新时间:2023-12-02 01:10:39 28 4
gpt4 key购买 nike

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

最佳答案

我有一个 C# 实现,但实际上很难将其放入此处。我将尝试总结所需的步骤。

大多数情况下,您需要从 OPC 核心组件可再发行组件包中获得 OpcRcw.Comn.dll 和 OpcRcw.Da.dll,可从 Opcfoundation.org 免费下载。安装后,文件位于 C:\Windows\assembly\GAC_MSIL。在您的项目中创建引用。

关于编码,这是你应该做的(你要实现三个对象,Server、Group和Item):

让我们从服务器开始:

 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.

关于opc - 从头开始实现 OPC DA 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17837952/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com