//--------------------------------------------------------- // 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; }