📄 datapoolpro.cpp
字号:
*
* 功能: 处理待处理(即向物理设备请求)的变量包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 + -