OPC数据订阅的方式,无法进入回调函数

Henley_Liang 2019-09-09 05:27:25
用OPC采集时候,写异步数据读取过程中,重写IOPCDataCallback接口里面的函数,具体里面如下,基本就简单实现各个事件显示了数据
COPCDataCallback::COPCDataCallback(void)
{
}

COPCDataCallback::~COPCDataCallback(void)
{
std::cout<<"释放回调函数"<<std::endl;
}


STDMETHODIMP COPCDataCallback::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
{
std::cout<<"11 触发数据变化事件"<<std::endl;
std::cout<<dwTransID<<std::endl;
int *value = new int [dwCount];
std::cout<<dwCount<<std::endl;
DWORD i;
for (i = 0; i<dwCount; i++)
{
std::cout<<typeid(pvValues[i].iVal).name()<<std::endl;
value[i] = pvValues[i].iVal;
/*quility[i] = GetQualityText(pwQualities[i]);
timestamp[i] = COleDateTime(pftTimeStamps[i]).Format();*/
std::cout<<value[i]<<std::endl;
}


std::cout << "数据变更完毕..." << std::endl;
return S_OK;
};

STDMETHODIMP COPCDataCallback::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
{
std::cout<<"12 触发异步读取事件"<<std::endl;
std::cout << std::endl;
std::cout << "数据获取中..." << std::endl;
int *value = new int [dwCount];
DWORD i;
for (i = 0; i<dwCount; i++)
{
value[i] = pvValues[i].iVal;
std::cout<<int(value[i])<<std::endl;
}
std::cout << "读取完毕" << std::endl;
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)
{
//Sleep(100);
std::cout<<"13 触发异步写入事件"<<std::endl;
std::cout << "数据已全部写完..." << std::endl;
return S_OK;
};

STDMETHODIMP_(ULONG) COPCDataCallback::AddRef ()
{
// Increment the reference count then return value:
std::cout<<"引用第"<<++m_cnRef<<"次";
return (m_cnRef);
}

STDMETHODIMP_(ULONG) COPCDataCallback::Release ()
{
// Decrement reference count and return immediately if not zero:
if (--m_cnRef != 0)
return (m_cnRef);


delete this;

// Return our refence count, which is zero now:
return (0);
}
STDMETHODIMP COPCDataCallback::QueryInterface (REFIID iid, LPVOID *ppInterface)
{
// Validate ppInterface. Return with "invalid argument" error code if invalid:
if (ppInterface == NULL)
return (E_INVALIDARG);


*ppInterface = NULL;

// Reset ppInterface if requested interface type is valid:
if (iid == IID_IUnknown)
*ppInterface = (IUnknown *) this;
else if (iid == IID_IOPCDataCallback)
*ppInterface = (IOPCDataCallback *) this;
else
{

return (E_NOINTERFACE);
}


AddRef ();

// Return with "success" code:
return (S_OK);
}

然后我把OPC Client配置等都写成一个类,再具体调用实现数据读取写入
我在进行异步读取的设置
hRev = m_pUnknown->QueryInterface (
IID_IConnectionPointContainer, (void **) &(m_pIConnPtContainer));
HRESULT hr = E_FAIL;

if (m_pIConnPtContainer)
{
// Get connection point (IID_IOPCDataCallback interface):
IConnectionPoint *pCP = NULL;
hr = m_pIConnPtContainer->FindConnectionPoint (IID_IOPCDataCallback, &pCP);
// If we succeeded to get connection point interface, create
// our data sink interface and advise server of it:
if (SUCCEEDED (hr))
{
try
{
// Instantiate a new IKDataSink20:
COPCDataCallback* m_callBack = new COPCDataCallback ();
// Advise the server of our data sink:
hr = pCP->Advise (m_callBack, &m_dwAdvise);
// We are done with the IID_IOPCDataCallback, so release
// (remove us from its reference count):
pCP->Release ();
}
catch (...)
{
// If a problem, make sure hr = E_FAIL so error gets
// processed correctly below:
std::cout<<"错误";
hr = E_FAIL;
}
}
}

最后我通过外部代用类来一步步测试同步读写,异步读写

ObjKepOpcDemo.CreateOPCServer("KEPware.KEPServerEx.V4");
ObjKepOpcDemo.AddGroups("Test.Simens01.test1", 0, 0.0, 0);
ObjKepOpcDemo.ItemList("Test.Simens01.test1",1);
ObjKepOpcDemo.AddItems();
ObjKepOpcDemo.GetIO();
ObjKepOpcDemo.AsyncSetting();
ObjKepOpcDemo.SyncRead();
//Sleep(1000);
ObjKepOpcDemo.SyncWrite(10);
//Sleep(1000);
//_getch();
ObjKepOpcDemo.AsyncRead();
//Sleep(1000);
ObjKepOpcDemo.AsyncWrite(13);
//Sleep(1000);
std::cout<<"休眠完了";
ObjKepOpcDemo.StopServer();
system("pause");

出现具体问题就如下
(1) 在我各个函数调试的时候,在类中函数加了断点,运行的时候就会能正常进入各个回调里面的事件中;
(2) 当我把断点取消后,运行的时候,就没有进入回调函数
运行结果如下图

就感觉没有进入这个事件;
(3) 在每一步加入sleep后
运行结果如下图

(4) 强制改变PLC数据也没有触发DataChange事件

已经卡在这个问题好几天,需要大牛知道,如果觉得麻烦,也可以有偿的指导。
...全文
266 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧