📄 devserver.cpp
字号:
}
return strProtocol;
}
/// 函数功能: 对一个Byte数组中的数值置位。
/// 函数返回: 成功返回TRUE。
/// 参数意义: byte 要操作的数组。
/// dData 预置值。
/// nBit 位序号。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
BOOL CDevServer::SvrSetByteBit(CByteArray& byte, double dData, int nBit)
{
if (byte.GetSize()*8 <= nBit)
{
ASSERT(FALSE);
return FALSE;
}
int nData = int(dData);
if (nData != 0) nData = 1;
BYTE bytTemp = byte[nBit/8];
bytTemp = (bytTemp & (0xff - (0x01<<(nBit%8))))|(nData<<(nBit%8));
byte[nBit/8] = bytTemp;
return TRUE;
}
/// 函数功能: 获取写命令的数值
/// 函数返回: 正确TRUE,错误FALSE。
/// 参数意义: strPara 用户设备命令中的参数值(字符型)
/// fParaVal 从命令中取回的数值(字符型)
/// 备 注: 如果是变量,则从数据中心取出变量的数据;
/// 如果是数值,则直接返回其数值
BOOL CDevServer::SvrGetParaValue(CString &strPara, float &fParaVal)
{
fParaVal = 0;
long nType = 0;
CString strVal(_T(""));
nType = g_datacentre.GetDataType(strPara);
switch (nType)
{
case VINTEGER:
{
long lParaVal = 0;
g_datacentre.GetValueFromName(strPara, lParaVal);
fParaVal = (float)lParaVal;
}
break;
case VSINGLE:
{
g_datacentre.GetValueFromName(strPara, fParaVal);
}
break;
case VSTRING:
{
ASSERT(FALSE);
return FALSE;
}
break;
default :
{
strVal = strPara.SpanIncluding(_T("1234567890."));
strVal.TrimLeft ();
strVal.TrimRight ();
if (strVal == _T(""))
{
fParaVal = 0;
}
else
{
_stscanf(strVal, _T("%f"), &fParaVal);
}
}
}
return TRUE;
}
/// 函数功能: 获取写命令的数值
/// 函数返回: 正确TRUE,错误FALSE。
/// 参数意义: strPara 用户设备命令中的参数值(字符型)
/// strParaVal 从命令中取回的数值(字符型)
/// 备 注: 如果是变量,则从数据中心取出变量的数据;
/// 如果是数值,则直接返回其数值
BOOL CDevServer::SvrGetParaValue(CString &strPara, CString &strParaVal)
{
strParaVal = _T("");
long nType = 0;
nType = g_datacentre.GetDataType(strPara);
switch (nType)
{
case VINTEGER:
{
ASSERT(FALSE);
return FALSE;
}
break;
case VSINGLE:
{
ASSERT(FALSE);
return FALSE;
}
break;
case VSTRING:
{
g_datacentre.GetValueFromName(strPara, strParaVal);
}
break;
default :
{
strParaVal = strPara;
}
}
return TRUE;
}
/// 函数功能: 设置数据中心数据变量的数值
/// 函数返回: 正确TRUE,错误FALSE。
/// 参数意义: strPara 用户设备命令中的参数值(字符型)
/// fParaVal 从命令中取回的数值(字符型)
/// 备 注: 如果是变量,则从数据中心取出变量的数据;
/// 如果是数值,则直接返回其数值
BOOL CDevServer::SvrSetParaValue(CString &strPara, float &fParaVal)
{
long nType = 0;
nType = g_datacentre.GetDataType(strPara);
switch (nType)
{
case VINTEGER:
{
long lParaVal = long(fParaVal);
g_datacentre.SetValueFromName(strPara, lParaVal);
}
break;
case VSINGLE:
{
g_datacentre.SetValueFromName(strPara, fParaVal);
}
break;
case VSTRING:
{
ASSERT(FALSE);
return FALSE;
}
break;
default :
{
ASSERT(FALSE);
return FALSE;
}
}
return TRUE;
}
/// 函数功能: 设置数据中心数据变量的数值
/// 函数返回: 正确TRUE,错误FALSE。
/// 参数意义: strPara 用户设备命令中的参数值(字符型)
/// strParaVal 从命令中取回的数值(字符型)
/// 备 注: 如果是变量,则从数据中心取出变量的数据;
/// 如果是数值,则直接返回其数值
BOOL CDevServer::SvrSetParaValue(CString &strPara, CString &strParaVal)
{
long nType = 0;
nType = g_datacentre.GetDataType(strPara);
switch (nType)
{
case VINTEGER:
{
ASSERT(FALSE);
return FALSE;
}
break;
case VSINGLE:
{
ASSERT(FALSE);
return FALSE;
}
break;
case VSTRING:
{
g_datacentre.SetValueFromName(strPara, strParaVal);
}
break;
default :
{
ASSERT(FALSE);
return FALSE;
}
}
return TRUE;
}
/// 函数功能: 解析命令字符串,把字符串按分割符分解成两部分。
/// 函数返回: 成功返回TRUE,失败返回FALSE。
/// 参数意义: strCmd 已去掉命令,只剩下数据和通道信息的命令字符串。
/// strDivision 命令字符串的分割字符。
/// strChannel 用来保存分割字符左边的字符串。
/// strData 用来保存分割字符右边的字符串。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
BOOL CDevServer::SvrGetCmdStr(CString& strCmd,
CString& strDivision,
CString& strLeft,
CString& strRight)
{
int nPos = strCmd.Find(strDivision);
if (nPos < 0)
{
return FALSE;
}
strLeft = strCmd.Left(nPos);
strRight = strCmd.Right(strCmd.GetLength() - nPos - 1);
strLeft.TrimLeft();
strLeft.TrimRight();
strRight.TrimLeft();
strRight.TrimRight();
return TRUE;
}
/// 函数功能: 写串口函数,往串口写一个字符串,用重叠操作的方式。
/// 函数返回: 成功返回TRUE,失败返回FALSE。
/// 参数意义: data MCGS传过来的MCGS_DATA结构的指针
/// nstrType 发送字符串协议类型,0:字符串协议。1:16进制协议。
/// str 用来保存写到串口的数据。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
BOOL CDevServer::SvrWriteComm(MCGS_DATA& data,
int nStrType,
CString& strProtocol)
{
CByteArray bytArProtocol;
switch (nStrType)
{
case DEV_PROTOCOL_ASII:
{
CDevServer::SvrStr2Byte(strProtocol, bytArProtocol);
}break;
case DEV_PROTOCOL_HEX:
{
CDevServer::SvrHStr2HByte(strProtocol, bytArProtocol);
}break;
default :
{
ASSERT(FALSE);
return FALSE;
}break;
}
TRACE(_T("\n串口输出:") + strProtocol + _T("\n"));
CDevServer c;
return c.SvrWriteComm(data, bytArProtocol);
}
/// 函数功能: 读串口函数,从串口读一个字符串,用重叠操作的方式。
/// 函数返回: 成功返回读取的字节数,失败返回<=0。
/// 参数意义: data MCGS传过来的MCGS_DATA结构的指针
/// nstrType 发送字符串协议类型,0:字符串协议。1:16进制协议。
/// str 数组用来保存从串口读回来的数据。
/// dwDelayTime 用来保存超时值。
/// nInputFlag 读串口的结束方式
/// 0:收到ucStopChar所指定的字符马上结束。
/// 1:收到dwInputLen个字符后马上结束。
/// 2:Sleep(dwDelayTime)后接收串口所有数据,结束。
/// 3:满足0或1中的条件马上结束。如果操作的时间
/// 超过了dwDelayTime所指定的时间则无条件退出。
/// dwInputLen 要接收的长度。
/// ucStopChar 停止字符。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
int CDevServer::SvrReadComm(MCGS_DATA& data,
int nStrType,
CString& strProtocol,
DWORD dwDelayTime,
int nInputFlag,
DWORD dwInputLen,
unsigned char ucStopChar)
{
CDevServer c;
CByteArray bytArProtocol;
int nLen = c.SvrReadComm(data, bytArProtocol, dwDelayTime,
nInputFlag, dwInputLen, ucStopChar);
switch (nStrType)
{
case DEV_PROTOCOL_ASII:
{
SvrByte2Str(bytArProtocol, strProtocol);
}break;
case DEV_PROTOCOL_HEX:
{
SvrHByte2HStr(bytArProtocol, strProtocol);
}break;
default :
{
ASSERT(FALSE);
return -1;
}break;
}
TRACE(_T("\n串口输入:") + strProtocol + _T("\n"));
return nLen;
}
/// 函数功能: 操作串口函数,发送命令并接收设备回应。
/// 函数返回: 成功返回读取的字节数,失败返回<=0。
/// 参数意义: data MCGS传过来的MCGS_DATA结构的指针
/// nstrType 发送字符串协议类型,0:字符串协议。1:16进制协议。
/// byteArray 数组用来保存从串口读回来的数据。
/// dwDelayTime 用来保存超时值。
/// nInputFlag 读串口的结束方式
/// 0:收到ucStopChar所指定的字符马上结束。
/// 1:收到dwInputLen个字符后马上结束。
/// 2:Sleep(dwDelayTime)后接收串口所有数据,结束。
/// 3:满足0或1中的条件马上结束。如果操作的时间
/// 超过了dwDelayTime所指定的时间则无条件退出。
/// dwInputLen 要接收的长度。
/// ucStopChar 停止字符。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
int CDevServer::SvrWriteAndReadComm(MCGS_DATA& data,
int nStrType,
CString& strProtocol,
DWORD dwDelayTime,
int nInputFlag,
DWORD dwInputLen,
unsigned char ucStopChar)
{
/// 清空串口输入缓冲区
SvrClearCommInBuff(data);
/// 发送命令
SvrWriteComm(data, nStrType, strProtocol);
/// 读取返回的数据
return SvrReadComm(data, nStrType, strProtocol,
dwDelayTime, nInputFlag, dwInputLen, ucStopChar);
}
int CDevServer::SvrReadTcpip(MCGS_DATA &data, CByteArray& byteArray)
{
if (!mfIsTcpipDev(data)) return 0;
HANDLE hHandle = (HANDLE)data.m_pParentData;
if (hHandle == NULL || hHandle == INVALID_HANDLE_VALUE)
{
ASSERT(FALSE);
return -1;
}
DWORD dwSize = 0;
CAsyncSocket *pSocket = (CAsyncSocket *)data.m_pParentData;
long lngRt = pSocket->IOCtl(FIONREAD, &dwSize);
if(dwSize == 0)
return 0;
if(lngRt == -1 )
///&& pSocket->GetLastError() == SOCKET_ERROR)
{
ASSERT(FALSE);
return -1;
}
byteArray.SetSize(dwSize);
lngRt = pSocket->Receive(byteArray.GetData(), byteArray.GetSize());
if(lngRt == -1)
///&& pSocket->GetLastError() == SOCKET_ERROR)
{
ASSERT(FALSE);
return -1;
}
return byteArray.GetSize();
}
int CDevServer::SvrWriteTcpip(MCGS_DATA &data, CByteArray& byteArray)
{
int iReturn, iError=0;
BOOL bSuccess = FALSE; // 是否发送成功. 假设失败
if (!mfIsTcpipDev(data)) return 0;
HANDLE hHandle = (HANDLE)data.m_pParentData;
if (hHandle == NULL || hHandle == INVALID_HANDLE_VALUE)
{
ASSERT(FALSE);
return -1;
}
CAsyncSocket* pSocket = (CAsyncSocket*)data.m_pParentData;
// 发送缓冲区大小, SO_SNDBUF. WinCE:16K, XP:8192
// int iSendBuffer, iIntSize = 4;
// pSocket->GetSockOpt(SO_SNDBUF, &iSendBuffer, &iIntSize, SOL_SOCKET);
// if(iSendBuffer != 50)
// {
// iSendBuffer = 50;
// iReturn = pSocket->SetSockOpt(SO_SNDBUF, &iSendBuffer, sizeof(int), SOL_SOCKET);
// }
#ifdef MCGSSET_ESET
// 模拟运行环境. 上位机运行环境的Socket是异步的,判断错误复杂
WSAEVENT hEventObject = WSACreateEvent(); // 事件对象
iReturn = WSAEventSelect(pSocket->m_hSocket, hEventObject, FD_WRITE); // 关联事件对象与网络事件FD_WRITE
#endif
iReturn = pSocket->Send(byteArray.GetData(), byteArray.GetSize());
// if(lngRt == -1 && pSocket->GetLastError() == SOCKET_ERROR)
// {
// ASSERT(FALSE);
// return -1;
// }
#ifdef MCGSSET_ESET
// 模拟运行环境. 上位机运行环境的Socket是异步的,要等待发送完成之后再判断发送错误
if(iReturn == -1)
{// 发送失败
iError = ::WSAGetLastError();
if(iError == WSAEWOULDBLOCK)
{// 异步发送未完成,等待完成
while(1)
{
DWORD dwReturn = WSAWaitForMultipleEvents(1, &hEventObject, FALSE, 300, FALSE);
if(dwReturn == WSA_WAIT_EVENT_0)
{// 连接完成
WSANETWORKEVENTS NetworkEvents;
WSAEnumNetworkEvents(pSocket->m_hSocket, hEventObject, &NetworkEvents);
if(NetworkEvents.lNetworkEvents & FD_WRITE)
{
int iErrorCode = NetworkEvents.iErrorCode[FD_WRITE_BIT];
if(iErrorCode == ERROR_SUCCESS)
{// 发送成功
bSuccess = TRUE;
}
else
{// 发送错误
;
}
WSASetLastError(iErrorCode); // 设置错误码,便于以后获取
iError = iErrorCode ;
}
break;
}
else if(dwReturn == WSA_WAIT_TIMEOUT)
{// 等待300ms超时,继续等待吧
;
}
else
{// 错误!WSAWaitForMultipleEvents()不应该返回错误码
iError = WSAGetLastError();
ASSERT(FALSE);
break;
}
}
}
else
{// 真正发送失败
;
}
}
else
{// 发送成功
bSuccess = TRUE;
}
WSAEventSelect(pSocket->m_hSocket, 0, 0); // 解除关联
WSACloseEvent(hEventObject); // 关闭事件
#else // 下位机运行环境. 下位机的Socket是同步的,判断错误很简单
iError = ::WSAGetLastError();
if(iReturn == -1)
{// 发送失败
ASSERT(::WSAGetLastError() != WSAEWOULDBLOCK); // 同步的Socket不可能返回这个错误码
}
else
{// 发送成功
bSuccess = TRUE;
}
#endif
{
// 写日志
if(((DEV_DATA*)data.m_pDevData)->bLog){
// 发送状态
CString strSend;
strSend.Format(_T("bSuccess=%d, iReturn = %d, iError=%d,"), bSuccess, iReturn, iError);
CDevBas::mfWriteLog(data, ((DEV_DATA*)data.m_pDevData)->dwLogN, _T("发送状态:"),
strSend, DEV_PROTOCOL_ASII);
((DEV_DATA*)data.m_pDevData)->dwLogN ++;
}
}
return bSuccess ? byteArray.GetSize() : -1 ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -