OPC客户端开发过程整理

OPC开发过程:
1.注册OPC接口组件
2.通过COM接口创建OPCServerList的接口指针
CoCreateInstance只能遍历本机,CoCreateInstanceEx可遍历远程机器OPC
CLSID_OPCServerList={0x13486D51, 0x4821, 0x11D2, { 0xA4, 0x94, 0x3C, 0xB3, 0x06, 0xC1, 0x00, 0x00 } };
IOPCServerList *pIOPCServerList = NULL;
CoCreateInstance(CLSID_OPCServerList, NULL, CLSCTX_SERVER, IID_IOPCServerList, (void **)&pIOPCServerList);
3.枚举OPC服务列表
通过IOPCServerList接口EnumClassesOfCategories方法,示例:
unsigned long c;
IEnumGUID *pIEnumGUID;
CLSID catid = CATID_OPCDAServer20;
pIOPCServerList->EnumClassesOfCategories(1, &catid, 1, &catid, &pIEnumGUID);
while(S_OK == pIEnumGUID->Next(1, &clsid, &c))
{
   char buf1[256]={0}, buf2[256]={0};
   LPOLESTR progID, pOPCName;
   pIOPCServerList->GetClassDetails(clsid, &progID, &pOPCName);
   WideCharToMultiByte(CP_ACP, 0, progID, -1, buf1, 256, NULL, NULL);
   WideCharToMultiByte(CP_ACP, 0, pOPCName, -1, buf2, 256, NULL, NULL);
   printf("OPC服务器: %s, %s\n", buf1, buf2);
}

3.连接OPC服务器
通过progID获取OPC服务器CLSID,利用CLSIDFromProgID()函数。
CoCreateInstanceEx启动远程OPC服务器,COSERVERINFO结构中的远程主机名称填IP和计算机全名称都可以,代码示例:
COSERVERINFO tCoServerInfo;
MULTI_QI m_arrMultiQI;  // array of interfaces we will query for each server
m_arrMultiQI.pIID = &IID_IOPCServer;
IOPCServer *m_pIServer;
CoCreateInstanceEx (
clsid,  // CLSID
NULL,  // No aggregation
CLSCTX_REMOTE_SERVER,  // connect to remote servers
&tCoServerInfo,  // remote machine name 
sizeof (m_arrMultiQI) / sizeof (MULTI_QI),  // number of IIDS to query
&m_arrMultiQI);
m_pIServer = (IOPCServer *)m_arrMultiQI.pItf;

4.断开OPC服务器连接
调用COM组件的Release接口,示例代码:
m_pIServer->Release();

5.遍历指定OPC服务上的Group
连接上指定OPC服务器后,可取得服务器状态,调用GetStatus(),结果存放在OPCSERVERSTATUS结构中。
遍历GROUP:
a.通过IOPCServer接口的CreateGroupEnumerator()创建IEnumUnknown以Group对象方式遍历Group,通过IEnumUnknown获取Group存取对像接口IOPCGroupStateMgt,
调用GetState返回此Group信息,示例代码:
IEnumUnknown *pEnum = NULL;
hr = m_pIServer->CreateGroupEnumerator (
eScope,  IID_IEnumUnknown, (IUnknown**)&pEnum);
IUnknown *pIUnknown;
ULONG uFetched;
IOPCGroupStateMgt *pIGroupStateMgt = NULL;
// Loop over enumerated groups (call enemerator's next member to
// reference next group and return its IUnknown interface):
while ((hr = pEnum->Next (1, &pIUnknown, &uFetched)) == S_OK)
{
// Get group state management interface of current group:
hr = pIUnknown->QueryInterface (IID_IOPCGroupStateMgt, (void**)&pIGroupStateMgt);

// Declare some variable needed to get the group name
// from the server:
OPCHANDLE hClient;
OPCHANDLE hServer;
WCHAR *pszName;

// Get group state (we are only interested in the group name):
hr = pIGroupStateMgt->GetState (
&m_dwUpdateRate,
&m_bActive,
&pszName, 
&m_lBias,
&m_fDeadband,
&m_dwLanguageID,
&hClient,
&hServer);
}
b.通过IOPCServer接口的CreateGroupEnumerator()创建IEnumString以Group名方式遍历Group,示例代码:
IEnumString *pEnum = NULL;
hr = m_pIServer->CreateGroupEnumerator (
eScope,  IID_IEnumString, (IUnknown**)&pEnum);
LPOLESTR pGroupName;
ULONG uFetched;

// Loop over enumerated groups (call enemerator's next member to
// reference next group and return its name string):
while ((hr = pEnum->Next (1, &pGroupName, &uFetched)) == S_OK)
{
}

6.遍历服务器Item项
通过OPCServer获取IOPCBrowseServerAddressSpace接口,调用BrowseOPCItemIDs方法,示例代码:
IOPCBrowseServerAddressSpace *pIOPCBrowseServerAddressSpace=NULL;
pIOPCServer->QueryInterface(IID_IOPCBrowseServerAddressSpace, (void **)&pIOPCBrowseServerAddressSpace);
LPENUMSTRING pPENUMSTRING;
hr = pIOPCBrowseServerAddressSpace->BrowseOPCItemIDs(OPC_BRANCH, L"", VT_EMPTY, 0, &pPENUMSTRING);

IOPCItemProperties *pIOPCItemProperties=NULL;
pIOPCServer->QueryInterface(IID_IOPCItemProperties, (void **)&pIOPCItemProperties);

ULONG count=0;
LPOLESTR pItemName, pItemID;
while(pPENUMSTRING->Next(1, &pItemName, &count) == S_OK)
{
char bufName[256]={0};
WideCharToMultiByte(CP_ACP, 0, pItemName, -1, bufName, 256, NULL, NULL);
printf("ITEM_NAME: %s\n", bufName);
pIOPCBrowseServerAddressSpace->GetItemID(pItemName, &pItemID);
WideCharToMultiByte(CP_ACP, 0, pItemID, -1, bufName, 256, NULL, NULL);
printf("ITEM_ID: %s\n", bufName);
DWORD dwCount;
DWORD *dwPropertyIDs;
LPWSTR *ppDescriptions;
VARTYPE *ppvtDataTypes;
VARIANT *ppvData;
HRESULT *ppErrors;
pIOPCItemProperties->QueryAvailableProperties(pItemID, &dwCount, &dwPropertyIDs, &ppDescriptions, &ppvtDataTypes);
pIOPCItemProperties->GetItemProperties(pItemID, dwCount, dwPropertyIDs, &ppvData, &ppErrors);

}
7.数据项ITEM读取
通过组Group取得ITEM项存取接口(IOPCSyncIO,IID_IOPCAsyncIO等),调用Write和Read方法。

8.总结
逻辑过程:
连接OPC服务器->得到服务器数据项->建立自定义组->将需要的服务器数据项加入到组中->取得项的存取接口->读写数据

猜你喜欢

转载自blog.csdn.net/liliaq/article/details/80968533