昨天又有人问我 OPC Client 编写,实际是他们不了解OPC 客户端的工作原理,要想写客户端程序,必须知道OPC对象, OPC逻辑对象模型包括3类对象:OPC server对象、OPC group对象、OPC item对象,每类对象都包括一系列接口。 OPC Server对象 主要功能为:1、创建和管理OPC Group对象; 2、管理服务器内部的状态信息; OPC Group对象 主要功能为:1、管理OPC Group对象的内部状态信息; 2、创建和管理Items对象。 3、OPC服务器内部的实时数据存取服务(同步与异步方式)。 OPC组中有以下几个主要属性:Name :组的名字 ;Active:组的激活状态标志 ;Update Rate OPC:服务器向客户程序提交数据变化的刷新速率;Percent Dead band:数据死区,即能引起数据变化的最小数值百分比。 OPC ITEM 是非COM对象,在OPC标准中用来描述实时数据,是客户端不可见的对象。代表了与服务器中的数据的连接,它并不是数据源,而仅仅是与数据源的连接。每个项都有以下主要属性: Active项的激活状态、Value项的数值、类型为VARIANT、Quality项的品质,代表数值的可信度,类型为SHORT、TimeStamp时间戳,代表数据的存取时间。 你不管用什么开发语言只要了解上面几个对象,就会写程序了 下面举个VC的例子 HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText; m_pItemResult = NULL; 客户端程序必须对DCOM进行初始化设置,以保证OPC服务器端 ![]() r1 = CoInitialize(NULL); if (r1 != S_OK) { if (r1 == S_FALSE) { MessageBox("COM Library already initialized", "Error CoInitialize()", MB_OK+MB_ICONEXCLAMATION); } else { szErrorText.Format("Initialisation of COM Library failed. Error Code= %4x", r1); MessageBox(szErrorText,"Error CoInitialize()", MB_OK+MB_ICONERROR); SendMessage(WM_CLOSE); return; } } 通过OPC服务器的ProgID查询注册表中相关CLSID。每个COM服务器都有一个字符串型的ProgID,通过ProgID可以得到全球惟一的CLSID,使用CLSIDFromProgID( )函数实现ProgID到CLSID的转换。 r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) { MessageBox("Retrival of CLSID failed", "Error CLSIDFromProgID()", MB_OK+MB_ICONERROR); CoUninitialize(); SendMessage(WM_CLOSE); return; } 连接OPC服务器,查询对象的IID_IOPCServer接口。在连接OPC服务器前,OPC客户端需要事先指定计算机名和OPC数据访问服务器名,建立连接后,创建OPC组并添加OPC数据项。 r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { MessageBox("Creation of IOPCServer-Object failed", "Error CoCreateInstance()", MB_OK+MB_ICONERROR); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); return; } 创建OPC组,查询IOPCItemMgt接口。IOPCServer接口的AddGroup()方法可以创建一个有指定名称和属性的OPC组。 r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ MessageBox("Can't add Group to Server!", "Error AddGroup()", MB_OK+MB_ICONERROR); m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); return; } 添加OPC数据项。使用IOPCItemMgt接口的AddItem()方法可以添加具有特殊属性的指定数量的数据项。 // define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; m_Items[0].szItemID = szItemID; // 影响数据类型 m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // defined by the item itself r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason |
|
来自: ThinkTank_引擎 > 《OPC》