📄 opcserver.cpp
字号:
NULL,
CLSCTX_ALL,
IID_IUnknown,
(LPVOID*)&punknown);
if(FAILED(hr) || punknown == NULL){ //创建失败
CString msg;
msg.Format(_T("CoCreateInstance %s failed:"), info->m_ProgID.GetBuffer(0));
theDoc->ReportError(msg, hr);
return false;
}
}
else{ //远程对象
COSERVERINFO si;
MULTI_QI qi;
si.dwReserved1 = 0;
si.pAuthInfo = NULL;
si.pwszName = T2OLE(info->m_NodeName.GetBuffer(0));
si.dwReserved2 = 0;
qi.pIID = &IID_IOPCServer;
qi.pItf = NULL;
qi.hr = 0;
hr = CoCreateInstanceEx(
info->m_clsid,
NULL,
CLSCTX_REMOTE_SERVER,
&si,
1,
&qi);
if(FAILED(hr)){
CString msg(_T("CoCreateInstanceEx failed: "));
theDoc->ReportError(msg, hr);
return false;
}
if(FAILED(qi.hr) || (qi.pItf == NULL)){
CString msg(_T("MULTI_QI failed: "));
theDoc->ReportError(msg, qi.hr);
return false;
}
punknown = qi.pItf;
}
hr = opc_server.Attach(punknown);
punknown->Release(); //释放IUnknown接口
punknown = NULL;
if(FAILED(hr)){
CString msg(_T("OPC Server Attach failed:"));
if(theDoc)
theDoc->ReportError(msg, hr);
}
//是否实现了IShutdown接口
hr = AtlAdvise(
opc_server,
shut_down->GetUnknown(),
IID_IOPCShutdown,
&shut_down_connection
);
if(FAILED(hr)){
CString msg;
msg.Format(_T("%s: %s can't support IOPCShutdown interface."),
info->m_NodeName,
info->m_ProgID);
if(theDoc)
theDoc->ReportError(msg.GetBuffer(0));
}
//添加所有组
/*
POSITION group_pos = groups.GetHeadPosition();
while(group_pos){
COPCGroup* group = groups.GetNext(group_pos);
if(!group)
continue;
group = add_group(group);
if(group){ //添加所有点
POSITION item_pos = group->items.GetHeadPosition();
while(item_pos){
Item* item = group->items.GetNext(item_pos);
if(!item)
continue;
item = group->add_item(item);
}
}
}
/*
HRESULT r1;
CLSID clsid;
COSERVERINFO sin, *sinptr;
MULTI_QI mqi;
LPWSTR LszNodeName;
DWORD clsctx;
LONG TimeBias = 0;
FLOAT PercentDeadband = 0.0;
DWORD RevisedUpdateRate;
// LPWSTR ErrorStr1,ErrorStr2;
CString szErrorText;
DWORD m_dwAdvise;
// r1 = CoInitialize(NULL);
LPWSTR Lopcservername;
Lopcservername=ConvertMultiByteToWideChar("KEPware.KEPServerEx.V4");
r1 = CLSIDFromProgID(Lopcservername, &clsid);
sinptr = &sin;
sin.dwReserved1 = sin.dwReserved2 = 0;
LszNodeName = ConvertMultiByteToWideChar("CSIT-ZKS");
sin.pwszName = LszNodeName; // szNodeName为本地或远程计算机名
sin.pAuthInfo = 0;
clsctx = CLSCTX_REMOTE_SERVER;//远程
mqi.pIID = &IID_IOPCServer;
mqi.hr = 0;
mqi.pItf = 0;
clsctx = CLSCTX_REMOTE_SERVER;//远程
r1 = CoCreateInstanceEx(clsid, NULL, clsctx, sinptr, 1, &mqi);// 创建OPC服务器的浏览器对象
m_pIOPCServer = (IOPCServer*)mqi.pItf;
r1=m_pIOPCServer->AddGroup(
L"grp1", // [in] group name
false, // [in] not active, so no OnDataChange callback
500, // [in] Request this Update Rate from Server
1000, // [in] Client Handle, not necessary in this sample
&TimeBias, // [in] No time interval to system UTC time
&PercentDeadband, // [in] No Deadband, so all data changes are reported
0, // [in] Server uses english language to for text values
&m_GrpSrvHandle, // [out] Server handle to identify this group in later calls
&RevisedUpdateRate, // [out] The answer from Server to the requested Update Rate
IID_IOPCGroupStateMgt,
(LPUNKNOWN*)&m_pIOPCGroupStateMgt); // [out] pointer to the requested interface
CComObject<COPCDataCallback>* pCOPCDataCallback; // Pointer to Callback Object
CComObject<COPCDataCallback>::CreateInstance(&pCOPCDataCallback);
LPUNKNOWN pCbUnk;
pCbUnk = pCOPCDataCallback->GetUnknown();
r1 = AtlAdvise( m_pIOPCGroupStateMgt, // [in] IUnknown Interface of the Connection Point
pCbUnk, // [in] IUnknown Interface of the Callback object
IID_IOPCDataCallback,// [in] Connection Point ID: The OPC Data Callback
&m_dwAdvise // [out] Cookie that that uniquely identifies the connection
);
*/
return true;
}
//断开OPCServer
bool COPCServer::disconnect()
{
if(!is_connected())
return false;
HRESULT hr = S_OK;
if(shut_down_connection){
hr = AtlUnadvise(
opc_server,
IID_IOPCShutdown,
shut_down_connection);
shut_down_connection = 0;
if(FAILED(hr)){
CString msg(_T("AtlUnadvise IOPCShutdown failed."));
if(theDoc)
theDoc->ReportError(msg.GetBuffer(0), hr);
}
}
//断开所有Group,并删除
/*.....*/
current_group = NULL;
while(!groups.IsEmpty())
delete groups.RemoveHead();
opc_server.Detach();
return true;
}
//连接状态
bool COPCServer::is_connected()
{
return opc_server.IsOk() ? true : false;
}
//获取错误信息
HRESULT COPCServer::GetErrorString(
HRESULT dwError,
LCID dwLocale,
LPWSTR* ppString)
{
return opc_server.GetErrorString(dwError, dwLocale, ppString);
}
OPCServerInfo* const COPCServer::get_server_info()
{
return server_info;
}
//添加点
COPCGroup* COPCServer::add_group(COPCGroup *group)
{
USES_CONVERSION;
if(!group)
return 0;
OPCServerInfo* info = server_info;
//add group
LPCWSTR group_name = T2OLE(group->get_name().GetBuffer(0));
BOOL active = group->get_active();
ULONG update_rate = group->get_update_rate();
long time_bias = group->get_time_bias();
float dead_band = group->get_dead_band();
DWORD local_id = group->get_local_id();
DWORD rate;
HRESULT hr = opc_server.AddGroup(
L"Chenmaoxiang",
active,
update_rate,
// (OPCHANDLE)group,
1000,
&time_bias,
&dead_band,
local_id,
&group->group_handle,
&rate,
IID_IOPCGroupStateMgt,
// group->opc_group);
(LPUNKNOWN*)&m_pIOPCGroupStateMgt);
if(FAILED(hr)){
CString msg;
msg.Format(_T("Add Group: %s failed."), group_name);
theDoc->ReportError(msg.GetBuffer(0), hr);
return 0;
}
#ifdef FULL_TEST
IOPCGroupStateMgt* pTest=NULL;
hr = opc_server.GetGroupByName(
L"Chenmaoxiang",
IID_IOPCGroupStateMgt,
(LPUNKNOWN*)&pTest );
if( SUCCEEDED(hr) )
{
ASSERT( pTest == (IOPCGroupStateMgt*)group->opc_group ); // should get the same
hr = pTest->SetName( group_name ); // set new name
pTest->Release();
if( FAILED(hr) )
{
theDoc->ReportError( _T("IOPCGroupStateMgt::SetName: "), hr );
}
else
{
// should now go by this new name
hr = opc_server.GetGroupByName(
group_name,
IID_IOPCGroupStateMgt,
(LPUNKNOWN*)&pTest );
if( SUCCEEDED(hr) )
{
ASSERT( pTest == (IOPCGroupStateMgt*)group->opc_group );
pTest->Release();
}
}
}
#endif//FULL_TEST
//ADD TEST
CComObject<COPCDataCallback>* pCOPCDataCallback; // Pointer to Callback Object
CComObject<COPCDataCallback>::CreateInstance(&pCOPCDataCallback);
LPUNKNOWN pCbUnk;
pCbUnk = pCOPCDataCallback->GetUnknown();
DWORD m_dwAdvise = 0;
//END TEST
//OPC 2.0 connection point
hr = AtlAdvise(
m_pIOPCGroupStateMgt,
pCbUnk,
IID_IOPCDataCallback,
&m_dwAdvise);
/*
hr = AtlAdvise(
group->opc_group,
group->call_back->GetUnknown(),
IID_IOPCDataCallback,
&group->call_back_connection);
*/
if(SUCCEEDED(hr))
group->use_cp = true;
if(!group->use_cp){ //不支持连接点
CString msg;
msg.Format(_T("%s: %s can't support IOPCDataCallback interface."),
info->m_NodeName,
info->m_ProgID);
theDoc->ReportError(msg.GetBuffer(0), hr);
//opc 1.0 data advise format
FORMATETC format_etc;
format_etc.tymed = TYMED_HGLOBAL;
format_etc.ptd = NULL;
format_etc.dwAspect = DVASPECT_CONTENT;
format_etc.lindex = -1;
// IAdviseSink is an interface on OUR object that is passed to
// the server for callbacks
IAdviseSink *pAdviseSink = NULL;
hr = group->advise_sink->QueryInterface(IID_IAdviseSink, (LPVOID *)&pAdviseSink);
if( FAILED(hr) )
{
msg = _T("IAdviseSink: ");
theDoc->ReportError(msg.GetBuffer(0), hr);
group->opc_group.Detach();
//opc_server.Detach();
return 0;
}
// Get an IDataObject interface on the group
DataObject dataObject;
hr = dataObject.Attach( group->opc_group );
if(FAILED(hr) || !dataObject.IsOk() )
{
//some servers don't do this, so don't quit altogether
msg = _T("IDataObject not supported by this server\nNo data notifications will take place");
theDoc->ReportError(msg.GetBuffer(0));
return 0;
}
// Register our IAdvise with the group
// Need to register both formats: data change, and write complete
format_etc.cfFormat = OPCSTMFORMATWRITECOMPLETE ;
hr = dataObject.DAdvise(&format_etc,
ADVF_PRIMEFIRST, // ADVF flag
pAdviseSink,
&group->connection2);
if( FAILED(hr) )
{
msg = _T("IDataObject::DAdvise: : ");
theDoc->ReportError(msg.GetBuffer(0), hr);
return 0;
}
#ifdef DATATIMEFORMAT
format_etc.cfFormat = OPCSTMFORMATDATATIME ;
#else
format_etc.cfFormat = OPCSTMFORMATDATA ;
#endif // DATATIMEFORMAT
hr = dataObject.DAdvise(&format_etc,
ADVF_PRIMEFIRST, // ADVF flag
pAdviseSink,
&group->connection1);
pAdviseSink->Release();
if( FAILED(hr) )
{
msg = _T("IDataObject::DAdvise: : ");
theDoc->ReportError(msg.GetBuffer(0), hr);
return 0;
}
}
groups.AddTail(group);
current_group = group;
theDoc->UpdateAllViews(NULL, ADD_GROUP, (CObject*)group);
return current_group;
}
//获取当前组
COPCGroup* COPCServer::get_current_group()
{
return current_group;
}
//获取父服务器
COPCServer* COPCGroup::get_parent() const
{
return parent;
}
OPCServer& COPCServer::get_opc_server()
{
return opc_server;
}
COPCGroup* COPCServer::set_current_group(COPCGroup *group)
{
if(group)
current_group = group;
return group;
}
//保存
void COPCServer::Serialize(CArchive &ar)
{
CWaitCursor wait_cursor;
//Lock wait(&item_cs);
if(ar.IsStoring()){
if(server_info){
ar << server_info->m_ProgID;
ar << server_info->m_NodeName;
ar << server_info->m_Description;
ar << server_info->m_clsid.Data1;
ar << server_info->m_clsid.Data2;
ar << server_info->m_clsid.Data3;
int times = sizeof(server_info->m_clsid.Data4) / sizeof(BYTE);
for(int i = 0; i < times; i++){
ar << server_info->m_clsid.Data4[i];
}
}
int group_count = groups.GetCount();
ar << group_count;
POSITION group_pos = groups.GetHeadPosition();
while(group_pos){
COPCGroup* group = groups.GetNext(group_pos);
if(group)
group->Serialize(ar);
}
}
else{
if(server_info)
delete server_info;
server_info = new OPCServerInfo;
if(server_info){
ar >> server_info->m_ProgID;
ar >> server_info->m_NodeName;
ar >> server_info->m_Description;
ar >> server_info->m_clsid.Data1;
ar >> server_info->m_clsid.Data2;
ar >> server_info->m_clsid.Data3;
int times = sizeof(server_info->m_clsid.Data4) / sizeof(BYTE);
for(int i = 0; i < times; i++){
ar >> server_info->m_clsid.Data4[i];
}
}
if(!is_connected()) //连接OPC Server
connect();
while(!groups.IsEmpty())
delete groups.RemoveHead();
int group_count = 0;
ar >> group_count;
while(group_count--){
COPCGroup* group = new COPCGroup;
if(group){
group->parent = this;
group->Serialize(ar);
//add_group(group);
//groups.AddTail(group);
}
}
}
}
//删除点
void COPCGroup::remove_item()
{
if(current_item == NULL)
return;
OPCItemMgt item_mgt;
HRESULT hr = item_mgt.Attach(opc_group);
if(SUCCEEDED(hr)){
HRESULT* errors = NULL;
hr = item_mgt.RemoveItems(
1,
¤t_item->hServerHandle,
&errors);
if(SUCCEEDED(hr))
CoTaskMemFree(errors);
EnterCriticalSection(&item_cs);
POSITION pos = items.Find(current_item);
if(pos)
items.RemoveAt(pos);
delete current_item;
current_item = NULL;
LeaveCriticalSection(&item_cs);
theDoc->SetModifiedFlag(TRUE);
theDoc->UpdateAllViews(NULL, UPDATE_GROUP, (CObject*)this);
}
}
void COPCServer::remove_group(COPCGroup *group)
{
Lock wait(&item_cs);
if(group == NULL){
group = current_group;
current_group = 0;
}
POSITION group_pos = groups.Find(group);
if(group_pos){
groups.RemoveAt(group_pos);
delete group;
}
theDoc->UpdateAllViews(NULL, UPDATE_SERVER, (CObject*)this);
}
//读取点
void COPCGroup::read_item(Item *item)
{
}
void COPCGroup::write_item(BOOL async, CString value, Item *item)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -