基于OPC协议的上位机PLC通讯 (二) 异步回调部分

//---------------------------------------------------------
// OPC Custom 2.0 Sample
// Asynchronous IO with MFC and ATL
// (c) Siemens AG 2000
//---------------------------------------------------------
//
// Callback.h : Declaration of callback class and definition of minor methods
//
#include "OPCRes.h"

class COPCDataCallback :public CComObjectRoot,public IOPCDataCallback
{
public:
COPCDataCallback() {};

BEGIN_COM_MAP(COPCDataCallback)
    COM_INTERFACE_ENTRY(IOPCDataCallback)
END_COM_MAP()

// IOPCDataCallback 
    STDMETHODIMP  OnDataChange( 
            /* [in] */ DWORD dwTransid,
            /* [in] */ OPCHANDLE hGroup,
            /* [in] */ HRESULT hrMasterquality,
            /* [in] */ HRESULT hrMastererror,
            /* [in] */ DWORD dwCount,
            /* [size_is][in] */ OPCHANDLE __RPC_FAR *phClientItems,
            /* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
            /* [size_is][in] */ WORD __RPC_FAR *pwQualities,
            /* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
            /* [size_is][in] */ HRESULT __RPC_FAR *pErrors);


    STDMETHODIMP  OnReadComplete( 
            /* [in] */ DWORD dwTransid,
            /* [in] */ OPCHANDLE hGroup,
            /* [in] */ HRESULT hrMasterquality,
            /* [in] */ HRESULT hrMastererror,
            /* [in] */ DWORD dwCount,
            /* [size_is][in] */ OPCHANDLE __RPC_FAR *phClientItems,
            /* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
            /* [size_is][in] */ WORD __RPC_FAR *pwQualities,
            /* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
            /* [size_is][in] */ HRESULT __RPC_FAR *pErrors);

        
        STDMETHODIMP  OnWriteComplete( 
            /* [in] */ DWORD dwTransid,
            /* [in] */ OPCHANDLE hGroup,
            /* [in] */ HRESULT hrMastererr,
            /* [in] */ DWORD dwCount,
            /* [size_is][in] */ OPCHANDLE __RPC_FAR *pClienthandles,
            /* [size_is][in] */ HRESULT __RPC_FAR *pErrors);

        
        STDMETHODIMP  OnCancelComplete( 
            /* [in] */ DWORD dwTransid,
            /* [in] */ OPCHANDLE hGroup) 
    {
        return S_OK;
    };

    void InformAbout (OPCRes *pOPCRes)
    {
        m_pOPCRes = pOPCRes;
    }

protected:
    OPCRes * m_pOPCRes;
};






实现callback.cpp

#include "stdafx.h"
#include "pre_opc.h"
#include "Callback.h"    // for OPC: include class declaration for this callback class
#include "../../HYWL01.h"
#include "../../MainDlg.h"
////////////////////////////////////

CString GetQualityText(UINT qnr);
//text description from quality code
/////////////////////////////////////////////////////////////////////////////
//
// IOPCDataCallback - implementation

// OnDataChange called by OPC server when the OPC server has detected modified data
// (being called only when group and item is set to active)
STDMETHODIMP COPCDataCallback:: OnDataChange(
                         /* [in] */ DWORD dwTransid,
                         /* [in] */ OPCHANDLE hGroup,
                         /* [in] */ HRESULT hrMasterquality,
                         /* [in] */ HRESULT hrMastererror,
                         /* [in] */ DWORD dwCount,
                         /* [size_is][in] */ OPCHANDLE __RPC_FAR *phClientItems,
                         /* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
                         /* [size_is][in] */ WORD __RPC_FAR *pwQualities,
                         /* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
                         /* [size_is][in] */ HRESULT __RPC_FAR *pErrors)
{
    DWORD i,j;
    for (i = 0; i<dwCount; i++)//除第一次,回调函数检测到有dwCount个值发生变化,i是控制循环遍历的次数 
    {
        for( j = 0 ; j<m_pOPCRes->GetAsyncCount() ;j++)// j用来遍历每一个项
        {
            if( (phClientItems[i] == j) && (pErrors[i] == S_OK) )//phClientItems[i]存放了有变化的异步项的序号
            {
                m_pOPCRes->m_ReadVal_A[j]=pvValues[i].intVal;
                m_pOPCRes->m_ReadQu_A[j].Format("%s",GetQualityText(pwQualities[i]));
                m_pOPCRes->m_ReadTs_A[j]=COleDateTime( pftTimeStamps[i] ).Format();
                break;
            }
        }
    }
    return S_OK;
};

STDMETHODIMP COPCDataCallback::OnReadComplete(
                          /* [in] */ DWORD dwTransid,
                          /* [in] */ OPCHANDLE hGroup,
                          /* [in] */ HRESULT hrMasterquality,
                          /* [in] */ HRESULT hrMastererror,
                          /* [in] */ DWORD dwCount,
                          /* [size_is][in] */ OPCHANDLE __RPC_FAR *phClientItems,
                          /* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
                          /* [size_is][in] */ WORD __RPC_FAR *pwQualities,
                          /* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
                          /* [size_is][in] */ HRESULT __RPC_FAR *pErrors)
{
    DWORD i;
    for (i = 0; i<dwCount; i++)
    {

        if( pErrors[i] == S_OK) 
        {
            m_pOPCRes->m_ReadVal_A[i]=pvValues[i].intVal;
            m_pOPCRes->m_ReadQu_A[i].Format("%s",GetQualityText(pwQualities[i]));
            m_pOPCRes->m_ReadTs_A[i]=COleDateTime( pftTimeStamps[i] ).Format();
        }
        else
        {
            /* error case: display error text */
            CString readQuality = GetQualityText(pErrors[i]);
            m_pOPCRes->m_ReadQu_A[i]=readQuality;
        }
    }
    return S_OK;
};
////////////////////////////////////////////////////////////////////////////////////////////
//异步写入未实现
STDMETHODIMP COPCDataCallback::OnWriteComplete(
                           /* [in] */ DWORD dwTransid,
                           /* [in] */ OPCHANDLE hGroup,
                           /* [in] */ HRESULT hrMastererr,
                           /* [in] */ DWORD dwCount,
                           /* [size_is][in] */ OPCHANDLE __RPC_FAR *pClienthandles,
                           /* [size_is][in] */ HRESULT __RPC_FAR *pErrors)
{

    return S_OK;
};
///////////////////////////////////////////////////////////////////////////////////////////

//品质值转换字符信息函数
CString GetQualityText(UINT qnr)
{
    CString qstr;
    switch(qnr)
    {
    case OPC_QUALITY_BAD:
        qstr = "BAD";
    break;
    case OPC_QUALITY_UNCERTAIN:
        qstr = "UNCERTAIN";
    break;
    case OPC_QUALITY_GOOD:
        qstr = "GOOD";
    break;
    case OPC_QUALITY_NOT_CONNECTED: 
        qstr = "NOT_CONNECTED";
    break;
    case OPC_QUALITY_DEVICE_FAILURE:
        qstr = "DEVICE_FAILURE";
    break;
    case OPC_QUALITY_SENSOR_FAILURE:
        qstr = "SENSOR_FAILURE";
    break;
    case OPC_QUALITY_LAST_KNOWN: 
        qstr = "LAST_KNOWN";
    break;
    case OPC_QUALITY_COMM_FAILURE: 
        qstr = "COMM_FAILURE";
    break;
    case OPC_QUALITY_OUT_OF_SERVICE:
        qstr = "OUT_OF_SERVICE";
    break;
    case OPC_QUALITY_LAST_USABLE:
        qstr = "LAST_USABLE";
    break;
    case OPC_QUALITY_SENSOR_CAL:
        qstr = "SENSOR_CAL";
    break;
    case OPC_QUALITY_EGU_EXCEEDED: 
        qstr = "EGU_EXCEEDED";
    break;
    case OPC_QUALITY_SUB_NORMAL:
        qstr = "SUB_NORMAL";
    break;
    case OPC_QUALITY_LOCAL_OVERRIDE:
        qstr = "LOCAL_OVERRIDE";
    break;
    default:
        qstr = "UNKNOWN ERROR";
    }
    return qstr;
}


你可能感兴趣的:(西门子,OPC,PLC,上位机)