⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datapoolpro.cpp

📁 组态王驱动的实例,这个例子与亚控的例子有很大不同
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DataPoolPro.cpp : implementation file
//

#include "stdafx.h"
#include "DataPool.h"
#include "DataPoolPro.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// DataPoolPro

IMPLEMENT_DYNCREATE(DataPoolPro, CCmdTarget)

DataPoolPro::DataPoolPro()
{
	EnableAutomation();
	
	// To keep the application running as long as an OLE automation 
	//	object is active, the constructor calls AfxOleLockApp.

	LIPAddr = INADDR_ANY;
	LIPPort = 6684;
	RIPAddr = 0x7f000001;
	RIPPort = 501;

	m_nTimeOut =5000;
	m_nLastErrorCode = -1;

	AfxOleLockApp();
}

DataPoolPro::~DataPoolPro()
{
	AfxOleUnlockApp();
}

void DataPoolPro::OnFinalRelease()
{
	// When the last reference for an automation object is released
	// OnFinalRelease is called.  The base class will automatically
	// deletes the object.  Add additional cleanup required for your
	// object before calling the base class.

	CCmdTarget::OnFinalRelease();
}

BEGIN_MESSAGE_MAP(DataPoolPro, CCmdTarget)
	//{{AFX_MSG_MAP(DataPoolPro)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


BEGIN_DISPATCH_MAP(DataPoolPro, CCmdTarget)
	//{{AFX_DISPATCH_MAP(DataPoolPro)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

/////////////////////////////////////////////////////////////////////////////
// DataPoolPro message handlers



// Note: we add support for IID_IDataPoolPro to support typesafe binding
//  from VBA.  This IID must match the GUID that is attached to the 
//  dispinterface in the .ODL file.

// {185EE497-6AE3-4530-BC1A-8EAAADEC1F33}
static const IID IID_IDataPoolPro =
{ 
	0x87556684, 0x0102, 0x0304, { 0x05, 0x06, 0x01, 0x23, 0x45, 0x67, 0x89, 0x02 } 
};

BEGIN_INTERFACE_MAP(DataPoolPro, CCmdTarget)
	INTERFACE_PART(DataPoolPro, IID_IDataPoolPro,  Dispatch)
	INTERFACE_PART(DataPoolPro, IID_ProtocolImp,   ProtocolImp)
END_INTERFACE_MAP()

// {40F58121-E7AA-47CD-8F86-97D4554A769C}
IMPLEMENT_OLECREATE(DataPoolPro, "DataPool.DataPoolPro", 
			0x87556684, 0x0102, 0x0304, 0x05, 0x06, 0x01, 0x23, 0x45, 0x67, 0x89, 0x04)

/////////////////////////////////////////////////////////////////////////////
// DataPoolPro message handlers

STDMETHODIMP_(ULONG) DataPoolPro::XProtocolImp::AddRef(void)
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
    return pThis->ExternalAddRef();
}

STDMETHODIMP_(ULONG) DataPoolPro::XProtocolImp::Release(void)
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
    return pThis->ExternalRelease();
}

STDMETHODIMP DataPoolPro::XProtocolImp::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
    return pThis->ExternalQueryInterface(&iid, ppvObj);
}

STDMETHODIMP_(char *) DataPoolPro::XProtocolImp::GetLastError()
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	
	if(pThis->m_nLastErrorCode != -1)
		return Error_Message_Table[pThis->m_nLastErrorCode];
	else
		return NULL;
}

/*
 * LoadDeviceInfo
 *
 * 功能: 加载本驱动程序的设备信息
 *
 */
STDMETHODIMP_(int) DataPoolPro::XProtocolImp::LoadDeviceInfo( const char *sProd, const char *sDevName, int nType )
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	return  TRUE;
}
/*
 * GetRegisters
 *
 * 功能: 返回本驱动程序提供的寄存器列表
 *
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp::GetRegisters(char *szDeviceName,LPVOID * ppRegs, int *pRegNum)
{	
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	*ppRegs = (LPVOID)&gsRegInfos;
	*pRegNum = REG_TYPE_NUM;
	return TRUE;
}
/*
 * OpenComDevice
 *
 * 功能: 打开本设备
 *
 * 参数: 
 *       nDeviceType - 设备类型
 *       lpInitData  - 初始化参数
 * 本驱动程序忽略这些参数
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp::OpenComDevice( int nDeviceType, LPVOID lpInitData)
{
	DWORD lip;
	char  Buf[32];

    METHOD_PROLOGUE(DataPoolPro, ProtocolImp); 

	if (GetProfileString("DataPool", "RIPADDR", "127.0.0.1", Buf, 24)) {
		if (pThis->ParseIPAddr(Buf, &lip)) {
			pThis->RIPAddr = lip;
		}
	}
	lip = GetProfileInt("DataPool", "RIPPort", 501);
	if (lip) pThis->RIPPort = (WORD)lip;

	if (GetProfileString("DataPool", "LIPADDR", "0.0.0.0", Buf, 24)) {
		if (pThis->ParseIPAddr(Buf, &lip)) {
			pThis->LIPAddr = lip;
		}
	}
	lip = GetProfileInt("DataPool", "LIPPort", 6684);
	if (lip) pThis->LIPPort = (WORD)lip;

	if (!pThis->SocketInit()) {
		pThis->m_nLastErrorCode = FAILED_OPEN_DEV;
		return (FALSE);
	}
	if (!pThis->SocketStart()) {
		pThis->m_nLastErrorCode = FAILED_OPEN_DEV;
		return (FALSE);
	}
	return (TRUE);
}
/*
 * InitialDevice
 *
 * 功能: 初始化设备 - 即对该设备的每一个地址地行初始化
 * 参数:
 *        pDeviceName - 组态王中设备的逻辑名字
 *        nUnitAddr   - ?
 *        lpDevAddr   - 由组态王中定义的, 并经StrToDevAddr解析过的设备地址
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp::InitialDevice(char * pDeviceName, int nUnitAddr, LPVOID lpDevAddr)
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	return (TRUE);
}

/*
 *  CloseComDevice
 *
 *  功能: 关闭已打开的设备
 *
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp::CloseComDevice()
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);	
	pThis->SocketStop(); 
	pThis->SocketEnds(); 
	return TRUE;
}
/*
 *  StrToDevAddr
 *
 *  功能: 解析设备地址
 *
 *  参数: 
 *        str         - 设备地址字符串
 *        lpDevAddr   - 解析过的设备地址存入此变量中
 *
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp::StrToDevAddr( const  char * str,LPVOID lpDevAddr)
{
	METHOD_PROLOGUE(DataPoolPro, ProtocolImp); 
	DEVADDR * pDevAddr =(DEVADDR *) lpDevAddr;
    char *p = (char *)str;
	while (*p) {
		if (!isdigit(*p)) return (FALSE);
		p++;
	}
	pDevAddr->nDevAddr = (atoi(str)&0x0f);
	strcpy(pDevAddr->sDevAddr, str);
	return (TRUE);
}

/*
 *  ConvertUserConfigToVar
 *
 *  功能: 解析组态王变量, 找到驱动内部对应的类型
 *
 *  参数:
 *
 *        lpDbItem - 指向组态王中MINIDBITEM型变量的指针
 *        lpVar    - 指向组态王PLCVAR型变量的指针
 *
 */
STDMETHODIMP_(WORD) DataPoolPro::XProtocolImp::ConvertUserConfigToVar( LPVOID lpDbItem, LPVOID lpVar )
{
	WORD r;
	METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	
	MiniDbItem * pTheDbItem = (MiniDbItem*)lpDbItem;

	CString strRegName;

	CString strDevName(pTheDbItem->szDevName);
	strRegName = pTheDbItem->szRegister;      
	
	r = pThis->MyConvert( lpDbItem, lpVar,
		gsRegInfos, REG_TYPE_NUM);

	return (r);
}

/*
 *  MyConvert
 *
 *  功能: 解析组态王变量, 找到驱动内部对应的类型
 *
 *  参数:
 *
 *        lpDbItem  - 指向组态王中MINIDBITEM型变量的指针
 *        lpVar     - 指向组态王PLCVAR型变量的指针
 *        lRegInfos - 指向本程序中关于寄存器定义的指针
 *        reg_type_num - 寄存器数量
 *
 */
WORD	DataPoolPro::MyConvert( LPVOID lpDbItem, LPVOID lpVar,
								LPVOID lRegInfos ,int reg_type_num)
{
	int         len;
	MINIDBITEM *pDbItem = (MINIDBITEM *)lpDbItem;
	PLCVAR     *pPlcVar = (PLCVAR *) lpVar;
	REG_INFO   *gsRegInfos = (REG_INFO *)lRegInfos;
	BYTE        bError = 0;	
	int         nRegType = 0;
	do {
		len = strlen(gsRegInfos->sRegName);
		if (strnicmp(pDbItem->szRegister, gsRegInfos->sRegName, len)==0) {
			if (pDbItem->nDataType != gsRegInfos->wDataType) {
				m_nLastErrorCode = USER_DATATYPEERR;         //数据类型错误
				return 1; 
			}

			char  *pChar = &pDbItem->szRegister[len];
			if (strlen(pChar)==0) {
				m_nLastErrorCode = USER_REGNAME_C_ERROR;     //寄存器名错误(含有非数字)
				return 1; 
			}

			char  *Ptr=pChar;
			while (*Ptr) {
				if ( (*Ptr <'0') || ( (*Ptr) >'9') ) {
					m_nLastErrorCode = USER_REGNAME_C_ERROR;  //寄存器名错误(含有非数字)
					return 1; 
				}
				Ptr++;
			}
				
			int nRegId = atoi(pChar);
			if (nRegId<gsRegInfos->nLowIndex || nRegId>gsRegInfos->nUpperIndex) {
				m_nLastErrorCode = USER_REGNAME_C_ERROR;         // 寄存器名错误, 编号越界
				return 1; 
			}

			pPlcVar ->pszRegName = gsRegInfos->sRegName;
			pPlcVar ->nRegType   = nRegType;
			pPlcVar ->nNo        = nRegId;
			pPlcVar ->nDataType  = pDbItem->nDataType;
	
			return 0;
		}
		gsRegInfos++;
		nRegType++;
	} while (nRegType<reg_type_num);

	m_nLastErrorCode = USER_REGNAME_C_ERROR;         // 寄存器名错误, 无此寄存器
	return 1; 
}

/*
 *  TryConnect
 *
 *  功能: 组态王测试通信状态用
 *
 *  说明: 这里通过发送一个请并得到一个应答来判断通信是否正常
 *
 *  参数: 
 *        pDeviceName - 组态王中设备的逻辑名字
 *        nUnitAddr   - ?
 *        lpDevAddr   - 由组态王中定义的, 并经StrToDevAddr解析过的设备地址
 *
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp::TryConnect( char * pDeviceName, int nUnitAddr, LPVOID lpDevAddr )
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	PDEVADDR pAddr = (PDEVADDR)lpDevAddr;


	int  nSendLen, nRecvLen;
	char ReadBuffer[1024];
	char SendBuffer[32];

	/* 构造请求帧 */
	nSendLen=8;                           /* 发送帧的长度            */
	SendBuffer[0] = 'R';                  /* 读寄存器指令            */
	SendBuffer[1] = 'D';                  /* 读寄存器的对象: A或D或W */
	SendBuffer[2] = 0;                    /* 读寄存器的地址: 0       */
	SendBuffer[3] = -1;                   /* CRC, 暂不用, 总设为0    */
	*((DWORD *)&SendBuffer[4]) = -1;      /* 帧序号, 暂不用, 总设为0 */

	/* 发送请求 */
	if ( !(pThis->PhysicalSend(SendBuffer, &nSendLen)) ) {
		/* 发送失败 */
		pThis->m_nLastErrorCode = FAILED_REQUEST;
		return (FALSE);
	}

	/* 发送请求成功, 则接收应答 */
	nRecvLen = 1024;
	if( !pThis->PhysicalReceive( ReadBuffer, &nRecvLen ) ) {
		pThis->m_nLastErrorCode = USER_TIMEOUT_EEROR; 
		return  FALSE;	
	}
	return (TRUE);
}

/* 
 * AddVarToPacket
 *
 * 功能: 把指定的变量lpVar打包到变量包lpPacket中
 *
 * 参数:
 *       lpVar          指定的变量
 *       lpPacket       输入/输出, 输入时包括了已经打包的变量, 输出则包含了指定的变量
 *       nVarAccessType 变量的访问类型, 只读, 只写, 读写
 * 
 * 返回:
 *       如果变量能加入到lpPacket中, 则返回TRUE, 否则返回FALSE.
 */
STDMETHODIMP_(BOOL) DataPoolPro::XProtocolImp:: AddVarToPacket( LPVOID lpVar, int nVarAccessType,LPVOID lpPacket)
{
	METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	
    PPACKET pPack = (PACKET *)lpPacket;
    PPLCVAR pVar  = (PLCVAR *)lpVar;

	int nCount = pPack->varList.GetCount(); /* 得到pPac中含有的变量数目 */
	if (nCount==0) {
		/* 目前还没有一个变量加入到Pack中 */
	}

	if (pPack->nDeviceIndex != pVar->nDeviceIndex   ||
		pPack->nUnitNo      != pVar->nUnitNo        ||
		strcmp(pPack->pszRegName, pVar->pszRegName) ){
		return (FALSE);
	}

	/* 现在已经知道, 要加入到包中的变量与包中的变量属同一设备同一地址的同一个寄存器 */

	/* 对于写操作, 只处理一个 */
	if ( nVarAccessType == PT_WRITE ) {
		//	MessageBox(NULL, pVar->szVarName, "REGName", MB_OK);
			if ( pVar->nNo == pPack->nStartNo )  
				return TRUE;
			else  
				return FALSE;
	}
	if ( nVarAccessType != PT_READ ) {
		// Read Operate 
		if ( pVar->nNo<pPack->nStartNo ) {
			//Graph:		-----no-------Start================End----------
			pPack->nStartNo = pVar->nNo;	
			return TRUE;
		} else if ( pVar->nNo > pPack->nEndNo ) {
			pPack->nEndNo = pVar->nNo;
			return TRUE;
		} else {
			//Graph:		------------Start====no============End----------
			return TRUE;
		}

	}

	return FALSE;		
}

/* 
 * ProcessPacket

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -