2004/10/27 | OPC客户端的原码工程实例!
类别(VC++天地) | 评论(4) | 阅读(1250) | 发表于 09:59
在网上看到很多的朋友要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服务器的数据了.界面图如下:
感兴趣的朋友可以和我联系!

图片如下:
0

评论Comments