OPC客戶端開發過程整理

greston發表於2014-06-26


2013-09-02 17:01:44|  分類: window其它 |  標籤:opc客戶端  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伺服器->得到伺服器資料項->建立自定義組->將需要的伺服器資料項加入到組中->取得項的存取介面->讀寫資料

相關文章