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

📄 datapoolpro.cpp

📁 组态王驱动的实例,这个例子与亚控的例子有很大不同
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 *
 * 功能: 处理待处理(即向物理设备请求)的变量包lpPacket
 *
 * 参数:
 *       lpPacket - 变量包       
 * 
 * 返回:
 *       如果能正常处理, 则返回TRUE, 否则返回FALSE.
 */
STDMETHODIMP_(int) DataPoolPro::XProtocolImp:: ProcessPacket( LPVOID lpPacket )
{
    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);
	
	PPACKET pPac = (PPACKET) lpPacket;
	if (pPac->nPacketType == PT_WRITE) {
		/* 对于写数据包, 调用读数据包例程处理 */
		return (pThis->UpdatePacket(pPac));
	}
	
	if (pPac->nPacketType == PT_READ) {
		/* 对于读数据包, 调用读数据包例程处理 */
		return (pThis->RequestPacket(pPac));
	}

	/* 对于其它的包, 直接返回FALSE, 表示已经处理 */
	pThis->m_nLastErrorCode = WRITE_UNSUPPORTED;
	return (FALSE);
}

/* 
 * RequestPacket
 *
 * 功能: 向物理设备请求数据
 *
 * 参数:
 *       lpPac - 变量包       
 * 
 * 返回:
 *       如果能正常处理, 则返回TRUE, 否则返回FALSE.
 */
BOOL  DataPoolPro::RequestPacket(PPACKET pPac)
{
	int  nSendLen, nRecvLen;
	char ObjType;
	char ReadBuffer[1024];
	char SendBuffer[32];

    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);	
	ObjType      = pPac->pszRegName[0];

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

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

	/* 发送请求成功, 则接收应答 */
	nRecvLen = 1024;
	if( !PhysicalReceive( ReadBuffer, &nRecvLen ) ) {
		/* 接收数据失败 */
		m_nLastErrorCode = USER_TIMEOUT_EEROR; 
		return  FALSE;
	}
	if (!nRecvLen) {
		m_nLastErrorCode = USER_TIMEOUT_EEROR; 
		return  TRUE;		
	}
	if (nRecvLen && ReadBuffer[0]=='E') {
		/* 应答给出的错误信息 */
		m_nLastErrorCode = REPLY_ERROR; 
		return  FALSE;
	}
	
	/* 处理接收到的正常应答数据 */
	POSITION position;
	ID_NO*   idNo;     
	int      varid ;	
	int      nCount;

	nCount    = pPac->varList.GetCount(); /* 得到pPac中含有的变量数目 */
	position  = pPac->varList.GetHeadPosition();
	for(int n=0;n<nCount;n++) {
		/* 依次取得每一个变量 */		
		idNo = (ID_NO*)(pPac->varList.GetNext(position));
		varid = idNo->wNo;
		if (ObjType=='D') {
			int iByte = varid / 8;
			int iBit  = varid % 8;
			char v    = ReadBuffer[8 + iByte];
			idNo->plcValue.bitVal = v & (1<<iBit);
		} else if (ObjType=='A') {
			idNo->plcValue.floatVal = *((float *)&ReadBuffer[8 + varid*sizeof(float)]);
		}
	}
	return (TRUE);
}

/* 
 * UpdatePacket
 *
 * 功能: 请求物理设备更新数据
 *
 * 参数:
 *       lpPac - 变量包       
 * 
 * 返回:
 *       如果能正常处理, 则返回TRUE, 否则返回FALSE.
 */
BOOL  DataPoolPro::UpdatePacket(PPACKET pPac)
{
	struct w_lem {
		BYTE	ObjType;
		BYTE	ObjNo;
		union {
		DWORD   w;
		float   f;
		} Value;
	} *RegPtr;

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

    METHOD_PROLOGUE(DataPoolPro, ProtocolImp);	
	ObjType      = pPac->pszRegName[0];

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

	RegPtr = (struct w_lem *)&SendBuffer[8];

	POSITION position;
	ID_NO*   idNo;     
	int      varid ;	
	int      nCount;

	nCount    = pPac->varList.GetCount(); /* 得到pPac中含有的变量数目 */
	position  = pPac->varList.GetHeadPosition();
	for(int n=0;n<nCount;n++) {
		/* 依次取得每一个变量 */		
		idNo = (ID_NO*)(pPac->varList.GetNext(position));
		varid = idNo->wNo;
		RegPtr->ObjType= ObjType;
		RegPtr->ObjNo  = (BYTE)idNo->wNo;
		if (ObjType=='D') {
			RegPtr->Value.w = idNo->plcValue.bitVal;
		} else if (ObjType=='A') {
			RegPtr->Value.f = idNo->plcValue.floatVal;
		}
		nSendLen += 8;
		if (nSendLen>512) {
			return (FALSE);
		}
		RegPtr++;
	}

	/* 发送更新请求 */
	if ( (PhysicalSend(SendBuffer, &nSendLen)) == 0) {		
		/* 发送失败 */
		m_nLastErrorCode = FAILED_REQUEST;
		return (FALSE);
	}	

	/* 发送请求成功, 则接收应答 */
	nRecvLen = 1024;
	if( !PhysicalReceive( ReadBuffer, &nRecvLen ) ) {
		/* 接收数据失败 */
		m_nLastErrorCode = USER_TIMEOUT_EEROR; 
		return  FALSE;
	}

	if (nRecvLen==nSendLen) {
		for (int i=0; i<nSendLen; i++) {
			if (ReadBuffer[i]!=SendBuffer[i]) {
				return (FALSE);
			}
		}
	}
	return (TRUE);
}

/*
 *  PhysicalSend
 *
 *  功能: 发送数据。
 *  参数: 
 *              char * buf:发送数据缓冲区。
 *              int   nLen:发送数据长度。
 *  返回: 
 *              int :成功发送数据个数(in byte)。
 *                    失败则为-1。
 */
BOOL DataPoolPro::PhysicalSend(char * buf, int *nLen)
{
	int rLen = SocketSend(sClient, buf, *nLen, this->RIPAddr, this->RIPPort);
	*nLen = rLen;
	return ((BOOL)nLen);
}

// Function name	: PhysicalRecive
// Description	    : 接收数据。
// Return type		: int :成功发送数据个数(in byte)。
//						失败则为-1。
// Argument         : char * buf:发送数据缓冲区。
// Argument         : int nLen:发送数据长度。
BOOL DataPoolPro::PhysicalReceive(char * pReceive, int *nLen)
{
	int                 RecvBytes;
	DWORD               dwRet;
	WSANETWORKEVENTS    Evs;
	DWORD               rip;
	WORD                rpo;

	while (1) {
		dwRet = WSAWaitForMultipleEvents(1, &Event, FALSE, m_nTimeOut, FALSE);
		switch (dwRet) {
		case WSA_WAIT_EVENT_0:
			break;
		case WSA_WAIT_TIMEOUT:
			return (FALSE);
		case WSA_WAIT_FAILED:
			WSAResetEvent( Event );
		default:
			continue;
		}
		if (WSAEnumNetworkEvents(sClient, Event, &Evs)==SOCKET_ERROR) {
			WSAResetEvent( Event );
			continue;
		}

		if (Evs.lNetworkEvents & FD_READ) {
			RecvBytes = SocketRecv(sClient, pReceive, *nLen, &rip, &rpo);
			*nLen = RecvBytes;
			return (TRUE);
		}
	}
	return FALSE;
}

/*
 *===========================================================
 * 
 * SOCKET 处理函数
 *
 *===========================================================
 */
bool DataPoolPro::SocketError() 
{ 
	WSAGetLastError();
    return true;
} 

bool DataPoolPro::SocketInit() 
{ 
    int             err; 
    WSADATA         wsaData; 

    err = WSAStartup( MAKEWORD(SOCKET_VER_MAJOR, SOCKET_VER_MINOR), &wsaData );
    if ( err != 0 ) { 
        SocketError(); 
        return false; 
    } 

    if (LOBYTE( wsaData.wVersion ) != SOCKET_VER_MAJOR || 
        HIBYTE( wsaData.wVersion ) != SOCKET_VER_MINOR ) { 
        WSACleanup( ); 
        SocketError(); 
        return false; 
    } 
    return true;
} 

bool DataPoolPro::SocketEnds() 
{ 
    if (WSACleanup()) { 
        SocketError();
    } 
    return true; 
} 

bool DataPoolPro::SocketStart() 
{ 
    // 启动本机作为流服务器 
    int         bReuse=1; 
    struct      sockaddr_in m_SocketAddr; 

	Event   = WSACreateEvent();
    sClient = socket(AF_INET, SOCK_DGRAM, 0); 
    if ( sClient == INVALID_SOCKET ) { 
        SocketError(); 
        return false ; 
    } 

	if (setsockopt(sClient, SOL_SOCKET, SO_REUSEADDR, 
        (const char FAR *)&bReuse, sizeof(int))==SOCKET_ERROR) { 
        closesocket(sClient); 
        sClient=INVALID_SOCKET; 
        return false ; 
    } 
	
    //将本机的地址捆扎到创建的套接字上 
    m_SocketAddr.sin_port        = htons((u_short)LIPPort); //服务端口号 
    m_SocketAddr.sin_addr.s_addr = htonl(LIPAddr);			//绑定的地址 
    m_SocketAddr.sin_family		 = AF_INET;					//internet 域 

    if (bind( sClient, 
        (const struct sockaddr FAR *)&m_SocketAddr, 
        sizeof(m_SocketAddr)) == SOCKET_ERROR ) { 
        SocketError(); 
        closesocket(sClient); 
        sClient=INVALID_SOCKET; 
        return false ; 
    } 

	if (WSAEventSelect(sClient, Event, FD_READ)) {
		closesocket(sClient);
        sClient=INVALID_SOCKET; 
		return false;
	}

    return true ; 
} 

bool DataPoolPro::SocketStop() 
{ 
    if (sClient!=INVALID_SOCKET) { 
        closesocket(sClient); 
        sClient=INVALID_SOCKET; 
    } 

    return true; 
} 

int DataPoolPro::SocketRecv(SOCKET s, void *Buf, int dwLen,
	DWORD *ip, WORD *port)
{
	struct sockaddr_in m_SocketAddr;
	int    rt, adr_len;
	DWORD  recvbytes;

	adr_len = sizeof(struct  sockaddr_in);
	rt = recvfrom(s,
		(char *)Buf, (int)dwLen,
		0,
		(struct sockaddr FAR *)&m_SocketAddr,
		&adr_len);

	if (rt!=SOCKET_ERROR) {
		/* 消息来源: 地址和端口号 */
		*ip   = ntohl(m_SocketAddr.sin_addr.s_addr);         //地址
		*port = ntohs(m_SocketAddr.sin_port);                //端口号
		recvbytes = rt;
	} else {
		/* 如果出现错误, 且错误代码为WSAEMSGSIZE, 表明数据太长, 本次只接收了部分 */
		int  ErrID = WSAGetLastError();
		if (ErrID==WSAEMSGSIZE) {
			*ip   = ntohl(m_SocketAddr.sin_addr.s_addr);         //地址
			*port = ntohs(m_SocketAddr.sin_port);                //端口号
			recvbytes = dwLen;
		} else {
			recvbytes = 0;
		}
	}
	return recvbytes;
}

int DataPoolPro::SocketSend(SOCKET s, void *Buf, int dwLen, DWORD ip, WORD port)
{
	struct sockaddr_in m_SocketAddr;
	int rt;

	//将本机的地址捆扎到创建的套接字上
	m_SocketAddr.sin_port        = htons((u_short)port); //端口号
	m_SocketAddr.sin_addr.s_addr = htonl(ip);          //的地址
	m_SocketAddr.sin_family		 = AF_INET;					//internet 域

	rt = sendto (s, (char *)Buf, (int)dwLen, 0,
		(const struct sockaddr FAR *)&m_SocketAddr,
		sizeof(m_SocketAddr));
	if (rt!=SOCKET_ERROR) {
		return rt;
	}
	return 0;
}
/*
 *  ParseIPAddr
 * 
 *  功能: 把点记号的IP地址字符串转换成双字型IP地址
 *
 */
bool DataPoolPro::ParseIPAddr(char *sIP, DWORD *dwIP)
{
	DWORD w[6], a=0;
	char Buf[256], *p1, *p2;
	strcpy(Buf, sIP);
	strcat(Buf, ".");
	p1 = Buf;
	p2 = p1;

	while (*p2 && a<=3) {
		if (!isdigit(*p2)) {
			if (  *p2=='.' ) {
				if (p1==p2) {
					m_nLastErrorCode=DEV_ADDR_ERR;
					return (false);
				}
				*p2 = 0;
				w[a] = atoi(p1);
				a++;
				p2++;
				p1=p2;
			} else {
				m_nLastErrorCode=DEV_ADDR_ERR;
				return (false);
			}
		}
		p2++;
	}
	if (w[0]>255||w[1]>255||w[2]>255||w[3]>255) {
		m_nLastErrorCode=DEV_ADDR_ERR;
		return (false);
	}
	*dwIP = w[0]<<24|w[1]<<16|w[2]<<8|w[3];
	return (true);
}

⌨️ 快捷键说明

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