I am not familiar with OpenSCADA. However I have developed OPC clients in c++. If you are looking for a class id for an OPC server running locally, you can use this function:
CLSID clsid;
hr = CLSIDFromProgID(L"Matrikon.OPC.Simulation", &clsid);
printf("OPC Server clsid: %p %p %p %p%p%p%p%p%p%p%p\n", (void*)opcServerId.Data1, (void*)opcServerId.Data2, (void*)opcServerId.Data3, (void*)opcServerId.Data4[0], (void*)opcServerId.Data4[1], (void*)opcServerId.Data4[2], (void*)opcServerId.Data4[3], (void*)opcServerId.Data4[4], (void*)opcServerId.Data4[5], (void*)opcServerId.Data4[6], (void*)opcServerId.Data4[7]);
If you are connecting to an OPC server which is installed on a remote computer which has not been installed locally, you must create a connection to OPCEnum (hopefully installed on both local and remote computer). You can create an COM object on the remote server which will translate a OPC server name into a CLSID. Here is some code demonstrating this.
//the first part of an OPC client is to connect to the OPCEnum service on the remote machine so we can look up the clsid of the OPC Server (given as a string).
//This code should get a list of OPC servers on a remote or local machine assuming that OPCEnum is running.
const CLSID CLSID_OpcServerList = {0x13486D51,0x4821,0x11D2, {0xA4,0x94,0x3C, 0xB3,0x06,0xC1,0x0,0x0}}; //{ 0x50fa5e8c, 0xdfae, 0x4ba7, { 0xb6, 0x9a, 0x8f, 0x38, 0xc2, 0xfd, 0x6c, 0x27 } }; //{0x13486D50,0x4821,0x11D2, {0xA4,0x94,0x3C, 0xB3,0x06,0xC1,0x0,0x0}};
const IID IID_IOPCServerList = {0x13486D50,0x4821,0x11D2, {0xA4,0x94,0x3C, 0xB3,0x06,0xC1,0x0,0x0}}; //for some reason the interface IID is the same as the CLSID.
const IID IID_IOPCServerList2 = {0x9DD0B56C,0xAD9E,0x43EE, {0x83,0x05,0x48, 0x7F,0x31,0x88,0xBF,0x7A}};
IOPCServerList *m_spServerList = NULL;
IOPCServerList2 *m_spServerList2 = NULL;
COSERVERINFO ServerInfo = {0};
ServerInfo.pwszName = hostName; //L"localhost";
ServerInfo.pAuthInfo = NULL;
MULTI_QI MultiQI [2] = {0};
MultiQI [0].pIID = &IID_IOPCServerList;
MultiQI [0].pItf = NULL;
MultiQI [0].hr = S_OK;
MultiQI [1].pIID = &IID_IOPCServerList2;
MultiQI [1].pItf = NULL;
MultiQI [1].hr = S_OK;
// Create the OPC server object and query for the IOPCServer interface of the object
HRESULT hr = CoCreateInstanceEx (CLSID_OpcServerList, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &ServerInfo, 1, MultiQI); // ,IID_IOPCServer, (void**)&m_IOPCServer);
//hr = CoCreateInstance (CLSID_OpcServerList, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServerList, (void**)&m_spServerList);
if (hr == S_OK)
{
printf("Part1 okay\n");
m_spServerList = (IOPCServerList*)MultiQI[0].pItf;
//m_spServerList2 = (IOPCServerList2*)MultiQI[1].pItf;
}
else
{
printf("Co create returned: %p\n",(void *)hr);
m_spServerList = NULL;
//qDebug() << (void *)REGDB_E_CLASSNOTREG;
}
//try and get the class id of the OPC server on the remote host
CLSID opcServerId;
CLSID clsid;
if (m_spServerList)
{
hr=m_spServerList->CLSIDFromProgID(serverName,&opcServerId);
m_spServerList->Release();
}
else
{
hr = S_FALSE;
opcServerId.Data1 = 0;
clsid.Data1 = 0;
}
//try to attach to an existing OPC Server (so our OPC server is a proxy)
if (hr != S_OK)
{
wprintf(L"Couldn't get class id for %s\n Return value: %p", serverName, (void *)hr);
}
else
{
printf("OPC Server clsid: %p %p %p %p%p%p%p%p%p%p%p\n", (void*)opcServerId.Data1, (void*)opcServerId.Data2, (void*)opcServerId.Data3, (void*)opcServerId.Data4[0], (void*)opcServerId.Data4[1], (void*)opcServerId.Data4[2], (void*)opcServerId.Data4[3], (void*)opcServerId.Data4[4], (void*)opcServerId.Data4[5], (void*)opcServerId.Data4[6], (void*)opcServerId.Data4[7]);
}
// Create the OPC server object and query for the IOPCServer interface of the object.
//Do it on the remote computer.
MultiQI [0].pIID = &IID_IOPCServer;
MultiQI [0].pItf = NULL;
MultiQI [0].hr = S_OK;
if (opcServerId.Data1)
{
hr = CoCreateInstanceEx (opcServerId, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &ServerInfo, 1, MultiQI);
}
else
{
hr = S_FALSE;
}
if (hr != S_OK)
{
m_IOPCServer = NULL;
printf("Couldn't create server.\n");
}
else
{
//CoCreateInstanceEx should have returned an array of pointers to interfaces. Since we only asked for 1, lets just get it.
m_IOPCServer = (IOPCServer*) MultiQI[0].pItf;
printf("Created remote OPC server.\n");
}
Here is also some commented out code demonstrating how you can enumerate all remote OPC servers. Interestingly, you can get the CLSID for these remote servers, but I believe there is a separate COM object you must create on the remote computer in order to back calculate a readable name for these. (I looked into it, but didn't need it myself so I have forgotten which interface it was).
//list all the OPC interfaces.
CLSID catid[2];
catid[0]=CATID_OPCDAServer10; //= CATID_OPCDAServer10; //OPC1.0
catid[1] = CATID_OPCDAServer20;
IOPCEnumGUID *pEnumGUID;
hr = m_spServerList->EnumClassesOfCategories(2, catid, 0, NULL, (IEnumGUID**)&pEnumGUID);
printf("Enum Result: %u", (void*) hr);
if (hr == S_OK)
{
//pEnumGUID->Reset();
GUID serverGUID;
ULONG numberServers = 8;
//pEnumGUID->Next(maxServers,serverGUIDs, &numberServers);
while ((hr = pEnumGUID->Next (1, &serverGUID, &numberServers)) == S_OK)
{
WCHAR* wszProgID;
hr = ProgIDFromCLSID (serverGUID, &wszProgID); //This probably won't work unless the same OPC server is installed locally.
printf("server: %ls \n",wszProgID);
CoTaskMemFree (wszProgID);
};
}