在网上看到很多的朋友要OPC客户端的原码,我在网上找了一个C++类,包含了CHotOpcServer,CHotOpcGroup,CHotOpcItem三个主要类,对于实现OPC客户端起了很大的作用,简单不少.我最近做了一个,不过还不完善,仍有BUG,希望共同爱好的朋友共同完善了! 下面给出这三各类的部分原码! //CHotOpcServer // CHotOpcServer 命令目标 /*--------------------------------------------- CHotOpcServer类
desc:...
----------------------------------------------*/ class CHotOpcServer : public CObject { public:
CHotOpcServer(); CHotOpcServer(CString &strSerName,CString strRemote); virtual ~CHotOpcServer(); protected: //声明OPC相应接口 IOPCServer *m_pIServer; IOPCCommon *m_pICommon; IConnectionPointContainer *m_pIConnPtContainer; IOPCItemProperties *m_pIItemProps; IOPCBrowseServerAddressSpace *m_pIBrowse; IOPCServerPublicGroups *m_pIPublicGroups; IPersistFile *m_pIPersistFile;
IHotShutdown *m_pIShutdownSink; DWORD m_dwCookieShutdown; MULTI_QI m_arrMultiQI[7]; //接口数组,用于查询服务
typedef struct S_Flags { DWORD bIsKepServerEx : 1; DWORD Reserved : 31; } FLAGS;
FLAGS m_bfFlags;
CStringList *m_pServerList; //服务器名列表 CString m_strServerName; //服务器名称 CString m_strRemoteMachine;//机器地址或名 bool m_bConnected; // 列表管理 CHotOpcServer *m_pPrev; CHotOpcServer *m_pNext;
// 组管理 CHotOpcGroup *m_pGroupHead; DWORD m_cdwGroups;
void InitInterface(void); HRESULT GetCLSID (CLSID &clsid); public: INT DisplayComponent(BOOL bOpc2 = TRUE); INT GetServerCount(void); CString GetServerNameByIndex(int nIndex); void SetServerName (CString &strSerName); LPCTSTR GetServerName() {return (m_strServerName);} void SetRemoteMachine (CString &strRemoteMachine); LPCTSTR GetRemoteMachine () { if (m_strRemoteMachine.IsEmpty ()) return (NULL);
return (m_strRemoteMachine); } void ShutdownRequest (LPCTSTR lpszReason);
bool Connect (CString &strSerName, CString &strRemoteMachine); bool Connect(void); void Disconnect(void);
bool IsConnected () {return (m_bConnected);} bool IsKepServerEx () {return (m_bfFlags.bIsKepServerEx);} bool IsAlive ();
void Start (); void Stop ();
// cut/copy/paste void Copy (CFixedSharedFile &sf); void Paste (CFixedSharedFile &sf);
// list management void SetPrev (CHotOpcServer *pPrev) {m_pPrev = pPrev;} CHotOpcServer* GetPrev () {return (m_pPrev);}
void SetNext (CHotOpcServer *pNext) {m_pNext = pNext;} CHotOpcServer* GetNext () {return (m_pNext);}
// group management void AddGroup (CHotOpcGroup *pGroup, bool bLoadingProject = false); void AddClonedGroup (CHotOpcGroup *pClone);
void RemoveGroup (CHotOpcGroup *pGroup, bool bDelete = true); void RemoveAllGroups (bool bDelete = true);
CHotOpcGroup* GetGroupHead () {return (m_pGroupHead);}
bool GenerateGroupName (CString &strName); bool FindGroup (LPCTSTR lpszName); CHotOpcGroup *GetGroup (LPCTSTR lpszName);
// 所支持的接口 bool IsIServerSupported () {return (m_pIServer != NULL);} bool IsICommonSupported () {return (m_pICommon != NULL);} bool IsIConnectionPointContainerSupported () {return (m_pIConnPtContainer != NULL);} bool IsIItemPropertiesSupported () {return (m_pIItemProps != NULL);} bool IsIBrowsingSupported () {return (m_pIBrowse != NULL);} bool IsIServerPublicGroupsSupported () {return (m_pIPublicGroups != NULL);} bool IsIPersistFileSupported () {return (m_pIPersistFile != NULL);}
IOPCServer* GetIServer () {return (m_pIServer);} IOPCBrowseServerAddressSpace* GetIBrowse () {return (IsAlive () ? m_pIBrowse : NULL);} IOPCItemProperties* GetIItemProps () {return (m_pIItemProps);} virtual void Serialize(CArchive& ar); };
// ************************************************************************** //------------------------------------------------------ //继续IOPCShutdown接口 /*--------------------------------------------- CHotOpcServer类
desc:...
----------------------------------------------*/ class IHotShutdown : public IOPCShutdown { public: IHotShutdown (CHotOpcServer *pServer); ~IHotShutdown ();
// 实现IUnknow接口方法 STDMETHODIMP QueryInterface (REFIID iid, LPVOID *ppInterface); STDMETHODIMP_(ULONG) AddRef (); STDMETHODIMP_(ULONG) Release ();
// IOPCShutdown 接口方法 STDMETHODIMP ShutdownRequest (LPCWSTR lpwszReason);
private: DWORD m_cnRef; CHotOpcServer *m_pServer; }; class IKDataSink20 : public IOPCDataCallback { public: IKDataSink20 (); ~IKDataSink20 ();
// IUnknown Methods STDMETHODIMP QueryInterface (REFIID iid, LPVOID *ppInterface); STDMETHODIMP_(ULONG) AddRef (); STDMETHODIMP_(ULONG) Release ();
// IOPCDataCallback Methods STDMETHODIMP OnDataChange ( // OnDataChange notifications DWORD dwTransID, // 0 for normal OnDataChange events, non-zero for Refreshes OPCHANDLE hGroup, // client group handle HRESULT hrMasterQuality, // S_OK if all qualities are GOOD, otherwise S_FALSE HRESULT hrMasterError, // S_OK if all errors are S_OK, otherwise S_FALSE DWORD dwCount, // number of items in the lists that follow OPCHANDLE *phClientItems, // item client handles VARIANT *pvvalues, // item data WORD *pwQualities, // item qualities FILETIME *pftTimeStamps, // item timestamps HRESULT *pErrors); // item errors
STDMETHODIMP OnReadComplete ( // OnReadComplete notifications DWORD dwTransID, // Transaction ID returned by the server when the read was initiated OPCHANDLE hGroup, // client group handle HRESULT hrMasterQuality, // S_OK if all qualities are GOOD, otherwise S_FALSE HRESULT hrMasterError, // S_OK if all errors are S_OK, otherwise S_FALSE DWORD dwCount, // number of items in the lists that follow OPCHANDLE *phClientItems, // item client handles VARIANT *pvvalues, // item data WORD *pwQualities, // item qualities FILETIME *pftTimeStamps, // item timestamps HRESULT *pErrors); // item errors
STDMETHODIMP OnWriteComplete ( // OnWriteComplete notifications DWORD dwTransID, // Transaction ID returned by the server when the write was initiated OPCHANDLE hGroup, // client group handle HRESULT hrMasterError, // S_OK if all errors are S_OK, otherwise S_FALSE DWORD dwCount, // number of items in the lists that follow OPCHANDLE *phClientItems, // item client handles HRESULT *pErrors); // item errors
STDMETHODIMP OnCancelComplete ( // OnCancelComplete notifications DWORD dwTransID, // Transaction ID provided by the client when the read/write/refresh was initiated OPCHANDLE hGroup);
private: DWORD m_cnRef; };
// ************************************************************************** class CKAdviseSink : public IAdviseSink { public: CKAdviseSink ();
// IUnknown Methods STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppInterface); STDMETHODIMP_(ULONG) AddRef (); STDMETHODIMP_(ULONG) Release ();
// IAdviseSink Methods STDMETHODIMP_(void) OnDataChange (FORMATETC *pFormatEtc, STGMEDIUM *pMedium); STDMETHODIMP_(void) OnViewChange (unsigned long dwAspect, long lindex) {/*Not implemented*/}; STDMETHODIMP_(void) OnRename (LPMONIKER pmk) {/*Not implemented*/}; STDMETHODIMP_(void) OnSave () {/*Not implemented*/}; STDMETHODIMP_(void) OnClose () {/*Not implemented*/};
private:
protected: ULONG m_cRef; }; // ************************************************************************** // CHotOpcGroup 命令目标 /*--------------------------------------------- CHotOpcGroup类
desc:...
----------------------------------------------*/ class CHotOpcGroup : public CObject { public: // construction/destruction CHotOpcGroup (CHotOpcServer *pParent); ~CHotOpcGroup ();
public: // property accessor/manipulators void SetName (CString &strName) {m_strName = strName;} void SetName (LPCTSTR lpszName) {m_strName = lpszName;} LPCTSTR GetName () {return (m_strName);}
void SetUpdateRate (DWORD dwRate) {m_dwUpdateRate = dwRate;} DWORD GetUpdateRate () {return (m_dwUpdateRate);}
void SetLanguageID (LCID lcid) {m_dwLanguageID = lcid;} LCID GetLanguageID () {return (m_dwLanguageID);}
void SetActive (BOOL bActive, BOOL bApply = FALSE) { /*m_bActive = bActive;
// apply change to server now if (bApply && m_pIGroupState) { DWORD dwRevRate; // for [out] parm m_pIGroupState->SetState (NULL, &dwRevRate, &m_bActive, NULL, NULL, NULL, NULL);
// select the activated group CKMainWnd *pWnd = (CKMainWnd *) AfxGetMainWnd (); if (pWnd) pWnd->PostMessage (UM_SELECT_GROUP, 0, (LPARAM) this);
// log status LogMsg (IDS_SET_GROUP_ACTIVE_STATE, bActive, GetName ()); }*/ }
BOOL IsActive () {return (m_bActive);}
void SetBias (long lBias) {m_lBias = lBias;} long GetBias () {return (m_lBias);}
void SetDeadband (float fDeadband) {m_fDeadband = fDeadband;} float GetDeadband () {return (m_fDeadband);}
void SetServerHandle (OPCHANDLE hServer) {m_hServer = hServer;} OPCHANDLE GetServerHandle () {return (m_hServer);}
void SetValid (BOOL bValid) {m_bValid = bValid;} BOOL IsValid () {return (m_bValid);}
void SetUpdateMethod (DWORD dwMethod) {m_dwUpdateMethod = dwMethod;} DWORD GetUpdateMethod () {return (m_dwUpdateMethod);}
// flag accessor/manipulators void ForceDeletion (BOOL bSet) {m_bfFlags.bOnDeleteForceDeletion = bSet;} BOOL IsForceDeletion () {return (m_bfFlags.bOnDeleteForceDeletion);}
// OPC Specifics void Initialize (LPUNKNOWN pUnk); void Uninitialize (bool bDelete = true);
bool SetItemActiveState (CObArray &cItemList, DWORD cdwItems, bool bActive);
void ReadSync (CObArray &cItemList, DWORD cdwItems, bool bDeviceRead, bool bPostMsg = true); void WriteSync (CObArray &cItemList, CStringArray &cvalues, DWORD cdwItems);
void ReadAsync10 (CObArray &cItemList, DWORD cdwItems, bool bDeviceRead); void RefreshAsync10 (bool bDeviceRead); void WriteAsync10 (CObArray &cItemList, CStringArray &cvalues, DWORD cdwItems);
void ReadAsync20 (CObArray &cItemList, DWORD cdwItems); void RefreshAsync20 (bool bDeviceRead); void WriteAsync20 (CObArray &cItemList, CStringArray &cvalues, DWORD cdwItems);
CHotOpcGroup* Clone ();
void Start ();
void ExportCsv (CStdioFile &csv); void ImportCsv (CStdioFile &csv, CObArray &cItemList, DWORD &cdwItems);
// cut/copy/paste void Copy (CFixedSharedFile &sf); void Paste (CFixedSharedFile &sf);
// parent server access CHotOpcServer* GetParentServer () {return (m_pServer);}
// list management void SetPrev (CHotOpcGroup *pPrev) {m_pPrev = pPrev;} CHotOpcGroup* GetPrev () {return (m_pPrev);}
void SetNext (CHotOpcGroup *pNext) {m_pNext = pNext;} CHotOpcGroup* GetNext () {return (m_pNext);}
// item management void AddItems (CObArray &cItemList, DWORD dwCount, bool bLoadingProject = false);
void RemoveItems (CObArray &cItemList, DWORD dwCount, bool bDelete = true); void RemoveAllItems (bool bDelete = true);
CHotOpcItem* GetItemHead () {return (m_pItemHead);} DWORD GetItemCount () {return (m_cdwItems);}
bool IsIGroupStateMgtSupported () {return (m_pIGroupState != NULL);} bool IsIPublicGroupStateMgtSupported () {return (m_pIPublicGroupState != NULL);} bool IsIItemMgtSupported () {return (m_pIItemMgt != NULL);} bool IsISyncIOSupported () {return (m_pISync != NULL);} bool IsIAsyncIOSupported () {return (m_pIAsync != NULL);} bool IsIDataObjectSupported () {return (m_pIDataObject != NULL);} bool IsIAsyncIO2Supported () {return (m_pIAsync2 != NULL);} bool IsIConnectionPointContainerSupported () {return (m_pIConnPtContainer != NULL);}
IOPCItemMgt* GetIItemMgt () {return (m_pIItemMgt);} IOPCGroupStateMgt* GetIGroupStateMgt () {return (m_pIGroupState);} IOPCSyncIO* GetISyncIO () {return (m_pISync);}
private: bool MapStringValToVariant (CString &strvalue, VARIANT &vtVal, VARTYPE vtType);
typedef enum _tagGETARRELEMRET { tElement = 0, tEndRow, tInvalid, tOverflow, tDone } GETARRELEMRET;
GETARRELEMRET GetArrayElement (LPCTSTR szInBuff, int *pnStart, LPTSTR szOutBuff, int nBuffSize); bool MapStringValToArrayVariant (CString &strvalue, VARIANT *pvtSrc, VARIANT *pvtDst);
void AddItemToList (CHotOpcItem *pItem); void RemoveItemFromList (CHotOpcItem *pItem);
private: // properties CString m_strName; // group name
DWORD m_dwUpdateRate; // update rate in milliseconds LCID m_dwLanguageID; // language ID
BOOL m_bActive; // active state long m_lBias; // time bias in minutes float m_fDeadband; // percent deadband
OPCHANDLE m_hServer; // server handle for this group BOOL m_bValid; // TRUE if successfully added to the OPC server DWORD m_dwUpdateMethod; // update method used by this group (see globals.h)
typedef struct _flags { DWORD bOnDeleteForceDeletion : 1; // TRUE if the server should force deletion of group even if references exists // DWORD bOnDeleteRemoveItems : 1; // TRUE if the client should remove items before remove group DWORD Reserved : 31; } FLAGS;
FLAGS m_bfFlags;
// OPC specifics IOPCGroupStateMgt *m_pIGroupState; IOPCPublicGroupStateMgt *m_pIPublicGroupState; IOPCItemMgt *m_pIItemMgt; IOPCSyncIO *m_pISync; IOPCAsyncIO *m_pIAsync; IDataObject *m_pIDataObject; IOPCAsyncIO2 *m_pIAsync2; IConnectionPointContainer *m_pIConnPtContainer;
IKDataSink20 *m_pIDataSink20; DWORD m_dwCookieDataSink20;
CKAdviseSink *m_pIAdviseSink; DWORD m_dwCookieRead; DWORD m_dwCookieWrite;
// parent server CHotOpcServer *m_pServer;
// list management CHotOpcGroup *m_pPrev; CHotOpcGroup *m_pNext;
// item management CHotOpcItem *m_pItemHead; DWORD m_cdwItems;
public: virtual void Serialize(CArchive& ar); };
// ************************************************************************** // CHotOpcItem 命令目标 /*--------------------------------------------- CHotOpcItem类
desc:...
----------------------------------------------*/ class CHotOpcItem : public CObject { public: // construction/destruction CHotOpcItem (CHotOpcGroup *pParent); ~CHotOpcItem ();
public: // property accessor/manipulators void SetAccessPath (LPCTSTR strAccessPath) {m_strAccessPath = strAccessPath;} LPCTSTR GetAccessPath () {return (m_strAccessPath);}
void SetActive (BOOL bActive) {m_bActive = bActive;} BOOL IsActive () {return (m_bActive);}
void SetDataType (VARTYPE vtType) {m_vtDataType = vtType;} VARTYPE GetDataType () { if (m_vtvalue.vt != VT_EMPTY) return (m_vtvalue.vt);
return (m_vtDataType); }
void SetItemID (LPCTSTR strItemID) {m_strItemID = strItemID;} LPCTSTR GetItemID () {return (m_strItemID);}
void SetServerHandle (OPCHANDLE hServer) {m_hServer = hServer;} OPCHANDLE GetServerHandle () {return (m_hServer);}
void SetAccessRights (DWORD dwAccess) {m_dwAccessRights = dwAccess;} DWORD GetAccessRights () {return (m_dwAccessRights);}
void SetValid (BOOL bValid) { m_bValid = bValid;
if (!bValid) { m_wQuality = OPC_QUALITY_BAD_OUT_OF_SERVICE; m_cdwUpdates = 0; m_bTimeStamped = FALSE;
VariantInit (&m_vtvalue); } }
BOOL IsValid () {return (m_bValid);}
// data void UpdateData (VARIANT &vtVal, WORD wQuality); void UpdateData (VARIANT &vtVal, WORD wQuality, FILETIME &ftTimeStamp);
void Getvalue (CString &strvalue); LPCTSTR GetQuality (); void GetTimeStamp (CString &strTimeStamp); DWORD GetUpdateCount ();
// This can be dangerous!! VARIANT* Getvalue () {return (&m_vtvalue);}
// cut/copy/paste void Copy (CFixedSharedFile &sf); void Paste (CFixedSharedFile &sf);
// parent group access CHotOpcGroup* GetParentGroup () {return (m_pGroup);}
// list management void SetPrev (CHotOpcItem *pPrev) {m_pPrev = pPrev;} CHotOpcItem* GetPrev () {return (m_pPrev);}
void SetNext (CHotOpcItem *pNext) {m_pNext = pNext;} CHotOpcItem* GetNext () {return (m_pNext);}
// GUI management void SetWParam (WPARAM wParam) {m_wParam = wParam;} WPARAM GetWParam () {return (m_wParam);}
private: // properties CString m_strAccessPath; // access path CString m_strItemID; // fully qualified item ID BOOL m_bActive; // active state VARTYPE m_vtDataType; // server's canonical datatype DWORD m_dwAccessRights; // access rights OPCHANDLE m_hServer; // server handle for this item
typedef struct _flags { DWORD Reserved : 32; } FLAGS;
FLAGS m_bfFlags;
BOOL m_bValid; // TRUE if successfully added to an OPC server BOOL m_bTimeStamped; // TRUE if the last update included a timestamp
// data FILETIME m_ftTimeStamp; // timestamp attached to value WORD m_wQuality; // quality attached to value VARIANT m_vtvalue; // current value
DWORD m_cdwUpdates;
// parent server CHotOpcGroup *m_pGroup;
// list management CHotOpcItem *m_pPrev; CHotOpcItem *m_pNext;
// threading CCriticalSection m_csDataLock;
// GUI management WPARAM m_wParam; public: virtual void Serialize(CArchive& ar); };
篇幅有限,不再多说了,通过连接服务器,填加组,在填加项,就可以看到OPC服务器的数据了.界面图如下: 感兴趣的朋友可以和我联系!
图片如下:
 |