OPC读写Kepware(C++)

OPC读写Kepware(C++opc同步读写)

”rw“ 是kepserver6.5的OPF文件,需要kepserver6.5及以上版本才能打开OPF文件,打开后如下图。
在这里插入图片描述
将各种接口封装成类…
OpcClient.h

#include "opcda.h"               
#include "OpcError.h"
#include "iostream"
#include  "opccomn.h"
#define LOCALE_ID 0x409
using namespace std;

class OpcClient
{
public:
	OpcClient();
	~OpcClient();
	IOPCServer		*m_IOPCServer;
	IOPCItemMgt		*m_IOPCItemMgt;
	IOPCSyncIO		*m_IOPCSyncIO;
	OPCITEMDEF		m_Items[1];
	OPCITEMRESULT	*m_ItemResult;
	OPCHANDLE		m_GrpSrvHandle;
	HRESULT			*m_pErrors;
	bool			OpcClientBusy;

	int connectToServer(LPWSTR ProgID, LPWSTR GrpID);
	int addItemtoGrp(LPWSTR szItemID, VARTYPE vt_ItemType);
	
	int readShort(LPWSTR OPCServerProgID, LPWSTR groupID,LPWSTR szItemID, VARTYPE vt_ItemType);
	int writeShort(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, int value);
	float readFloat(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType);
	int writeFloat(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, float value);
	bool readBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType);
	int writeBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, bool value);
	int setBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType);
	int resetBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType);
	int invertBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType);
	int Stop();

private:

};

OpcClient.cpp

#include "stdafx.h"
#include "OpcClient.h"
int OpcClient::connectToServer(LPWSTR ProgID, LPWSTR GrpID)
{
	OpcClientBusy = true;
	HRESULT			r1;
	CLSID			clsid;
	LONG			TimeBias = 0;
	FLOAT			PercentDeadband = 0.0;
	DWORD			RevisedUpdateRate;
	//初始化COM库
	m_ItemResult = NULL;
	r1 = CoInitialize(NULL);
	//通过ProgID,查找注册表中的机关CLSID
	r1 = CLSIDFromProgID(ProgID, &clsid);
	if (FAILED(r1))
	{
		CoUninitialize();
		return 1;
	}
	//创建 OPC服务对象,并查询对象的IID_IOPCServer接口
	r1 = CoCreateInstance(clsid, NULL,
		CLSCTX_LOCAL_SERVER, IID_IOPCServer,
		(void**)&m_IOPCServer);
	if (r1 != S_OK)
	{
		m_IOPCServer = NULL;
		CoUninitialize();
		return 2;
	}
	//添加一个Group,并查询IOPCItemMgt接口
	r1 = m_IOPCServer->AddGroup(GrpID,
		TRUE,
		500,
		1,
		&TimeBias,
		&PercentDeadband,
		LOCALE_ID,
		&m_GrpSrvHandle,
		&RevisedUpdateRate,
		IID_IOPCItemMgt,
		(LPUNKNOWN*)&m_IOPCItemMgt);
	if (r1 == OPC_S_UNSUPPORTEDRATE)
	{
		return 3;
	}
	else if (FAILED(r1))
	{
		m_IOPCServer->Release();
		m_IOPCServer = NULL;
		CoUninitialize();
		return 4;
	}
	return 0;
}
int OpcClient::addItemtoGrp(LPWSTR szItemID, VARTYPE vt_ItemType)
{
	if (OpcClientBusy == false)
	{
		return 1;
	}
	HRESULT r1;
	//为ADDItem定义item表的参数
	m_Items[0].szAccessPath = L"";
	m_Items[0].szItemID = szItemID;
	m_Items[0].bActive = TRUE;
	m_Items[0].hClient = 1;
	m_Items[0].dwBlobSize = 0;
	m_Items[0].pBlob = NULL;
	m_Items[0].vtRequestedDataType = vt_ItemType;
	r1 = m_IOPCItemMgt->AddItems(1,
		m_Items,
		&m_ItemResult,
		&m_pErrors);

	if (r1 == S_OK)
	{
		//cout << "ADDItems()成功!" << endl;
	}
	if ((r1 != S_OK) && (r1 != S_FALSE))
	{
		//cout << "ADDItems失败!!" << endl;
		m_IOPCItemMgt->Release();
		m_IOPCItemMgt = NULL;
		m_GrpSrvHandle = NULL;
		m_IOPCServer->Release();
		m_IOPCServer = NULL;
		CoUninitialize();
		return 1;
	}
	//检测Itemr的可读可写性
	if (m_ItemResult[0].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE))
	{
		return 2;
	}
	else
	{
		//
	}

	//查询group对象的同步接口
	r1 = m_IOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_IOPCSyncIO);
	if (r1<0)
	{
		CoTaskMemFree(m_ItemResult);
		m_IOPCItemMgt->Release();
		m_IOPCItemMgt = NULL;
		m_GrpSrvHandle = NULL;
		m_IOPCServer->Release();
		m_IOPCServer = NULL;
		CoUninitialize();
		return 3;
	}
	return 0;
}
int OpcClient::readShort(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType)
{
	OpcClient::connectToServer(OPCServerProgID, groupID);
	OpcClient::addItemtoGrp(szItemID, vt_ItemType);

	OPCHANDLE		*phServer;
	OPCITEMSTATE	*pItemValue;
	HRESULT			*pErrors;
	HRESULT			r1 = E_FAIL;

	if (m_pErrors[0] != S_OK)
	{
		return 32767;
	}
	//内存分配
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[0].hServer;
	r1 = m_IOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer, &pItemValue, &pErrors);
	//释放内存
	delete[]phServer;

	if (r1 == S_OK)
	{
		//
	}
	else
	{
		Stop();
		return 32767;
	}
	Stop();
	return pItemValue[0].vDataValue.intVal;
}
int OpcClient::writeShort(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, int value)
{
	OpcClient::connectToServer(OPCServerProgID, groupID);
	OpcClient::addItemtoGrp(szItemID, VT_I2);
	OPCHANDLE *phServer;
	HRESULT *pErrors;
	VARIANT	values[1];
	HRESULT r1;
	LPWSTR	ErrorStr;

	if (m_pErrors[0] != S_OK)
	{
		Stop();
		return 1;
	}
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[0].hServer;

	values[0].vt = VT_I2;
	values[0].intVal = value;
	r1 = m_IOPCSyncIO->Write(1, phServer, values, &pErrors);
	delete[]phServer;
	Stop();
	return 0;
}
float OpcClient::readFloat(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType)
{
	OpcClient::connectToServer(OPCServerProgID, groupID);
	OpcClient::addItemtoGrp(szItemID, vt_ItemType);
	OPCHANDLE		*phServer;
	OPCITEMSTATE	*pItemValue;
	HRESULT			*pErrors;
	HRESULT			r1 = E_FAIL;
	if (m_pErrors[0] != S_OK)
	{
		return 32767;
	}
	//内存分配
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[0].hServer;
	r1 = m_IOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer, &pItemValue, &pErrors);
	//释放内存
	delete[]phServer;

	if (r1 == S_OK)
	{
		//
	}
	Stop();
	return pItemValue[0].vDataValue.fltVal;
}
int OpcClient::writeFloat(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, float value)
{
	OpcClient::connectToServer(OPCServerProgID, groupID);
	OpcClient::addItemtoGrp(szItemID, VT_R4);
	OPCHANDLE *phServer;
	HRESULT *pErrors;
	VARIANT	values[1];
	HRESULT r1;
	LPWSTR	ErrorStr;

	if (m_pErrors[0] != S_OK)
	{
		return;
	}
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[0].hServer;

	//UpdateData(TRUE); 
	values[0].vt = VT_R4;
	values[0].fltVal = value;
	r1 = m_IOPCSyncIO->Write(1, phServer, values, &pErrors);
	delete[]phServer;
	Stop();
	return 0;
}
bool OpcClient::readBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType)
{
	OpcClient::connectToServer(OPCServerProgID, groupID);
	OpcClient::addItemtoGrp(szItemID, vt_ItemType);
	OPCHANDLE		*phServer;
	OPCITEMSTATE	*pItemValue;
	HRESULT			*pErrors;
	HRESULT			r1 = E_FAIL;
	if (m_pErrors[0] != S_OK)
	{
		return 32767;
	}

	phServer = new OPCHANDLE[1];

	phServer[0] = m_ItemResult[0].hServer;
	r1 = m_IOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer, &pItemValue, &pErrors);
	//释放内存
	delete[]phServer;
	if (r1 == S_OK)
	{
		//
	}
	Stop();
	if (pItemValue[0].vDataValue.boolVal==-1)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int OpcClient::writeBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, bool value)
{
	OpcClient::connectToServer(OPCServerProgID, groupID);
	OpcClient::addItemtoGrp(szItemID, VT_R4);
	OPCHANDLE *phServer;
	HRESULT *pErrors;
	VARIANT	values[1];
	HRESULT r1;
	LPWSTR	ErrorStr;

	if (m_pErrors[0] != S_OK)
	{
		return;
	}
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[0].hServer;

	values[0].vt = VT_R4;
	values[0].boolVal = value;
	r1 = m_IOPCSyncIO->Write(1, phServer, values, &pErrors);
	delete[]phServer;
	Stop();
	return 0;
}

int OpcClient::setBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType)
{
	writeBool(OPCServerProgID, groupID, szItemID, true);
	if (readBool(OPCServerProgID, groupID, szItemID, VT_BOOL))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
int OpcClient::resetBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType)
{
	writeBool(OPCServerProgID, groupID, szItemID, false);
	if (readBool(OPCServerProgID, groupID, szItemID, VT_BOOL))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
int OpcClient::invertBool(LPWSTR OPCServerProgID, LPWSTR groupID, LPWSTR szItemID, VARTYPE vt_ItemType)
{
	if (readBool(OPCServerProgID, groupID, szItemID, VT_BOOL) == false)
	{
		writeBool(OPCServerProgID, groupID, szItemID, true);
		return 0;
	}
	if (readBool(OPCServerProgID, groupID, szItemID, VT_BOOL) == true)
	{
		writeBool(OPCServerProgID, groupID, szItemID, false);
		return 0;
	}
}

int OpcClient::Stop()
{
	if (OpcClientBusy == false)
	{
		return 1;

	}
	HRESULT r1;
	OPCHANDLE *phServer;
	HRESULT *pErrors;
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[0].hServer;
	r1 = m_IOPCItemMgt->RemoveItems(0,
		phServer,
		&pErrors
		);
	delete[]phServer;
	CoTaskMemFree(pErrors);
	CoTaskMemFree(m_ItemResult);
	m_ItemResult = NULL;
	m_IOPCSyncIO->Release();
	m_IOPCSyncIO = NULL;
	m_IOPCItemMgt->Release();
	m_IOPCItemMgt = NULL;
	r1 = m_IOPCServer->RemoveGroup(m_GrpSrvHandle, true);
	m_GrpSrvHandle = NULL;
	m_IOPCServer->Release();
	m_IOPCServer = NULL;
	CoUninitialize();
	OpcClientBusy = false;
	return 0;
}

OpcClient::OpcClient()
{

	OpcClientBusy = false;//初始化为false
}

OpcClient::~OpcClient()
{
	//
}

mian函数

// OpcClient.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include "OpcClient.h"
using namespace std;

OpcClient ObjKepOpc;
int _tmain(int argc, _TCHAR *argv[])
{
	const LPWSTR OPCServerProgID = L"Kepware.KEPServerEX.V6";//服务器ProID
	const LPWSTR groupID = L"King.Win7";//GroupID,通道.设备
	const LPWSTR ritem_1 = L"King.Win7.Tag_1";//item格式,通道.设备.item
	const LPWSTR ritem_2 = L"King.Win7.Tag_2";//item格式,通道.设备.item

	const LPWSTR witem_1 = L"King.Win7.Tag_1_write";//item格式,通道.设备.item
	const LPWSTR witem_2 = L"King.Win7.Tag_2_write";//item格式,通道.设备.item
	ObjKepOpc.connectToServer(OPCServerProgID, groupID);
	while(1)
	{
		//读
		float r1 = ObjKepOpc.readFloat(OPCServerProgID, groupID,ritem_1, VT_R4);
		float r2 = ObjKepOpc.readFloat(OPCServerProgID, groupID,ritem_2, VT_R4);
		cout<< r1 <<endl;
		cout<< r2 <<endl;
		//写
		ObjKepOpc.writeFloat(OPCServerProgID, groupID,witem_1,r1);
		ObjKepOpc.writeFloat(OPCServerProgID, groupID,witem_2,r2);
	}
	return 0;
}

在这里插入图片描述

完整项目:
https://download.csdn.net/download/weixin_37928884/86881385