📄 devserver.cpp
字号:
/// 函数返回: 成功返回TRUE失败返回FALSE。
/// 参数意义: data MCGS传过来的MCGS_DATA结构的指针
/// byteArray 用来保存从串口读回来的数据。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
inline BOOL CDevServer::mfReadComm(MCGS_DATA &data, CByteArray& byteArray)
{
byteArray.SetSize(0);
if (!mfIsCommDev(data)) return FALSE;
DWORD dwErrorFlags = 0;
COMSTAT ComStat;
ClearCommError(data.m_pParentData, &dwErrorFlags, &ComStat);
if (dwErrorFlags > 0)
{
/// ASSERT(FALSE);考虑到这个错误发生是正常的所以不做断言了。
TRACE(_T("串口发生一个错误!\n"));
return FALSE;
}
BOOL bRes = TRUE;
if (ComStat.cbInQue > 0)
{
/// 输入缓冲有数据,则读取
DWORD dwLength = ComStat.cbInQue;
byteArray.SetSize(dwLength);
#ifdef MCGSSET_ESET
/// 这一段是在组态和模拟运行环境下用的代码
OVERLAPPED os;
memset(&os, 0, sizeof(OVERLAPPED));
os.Offset = 0;
os.OffsetHigh = 0;
if ((os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
{
byteArray.SetSize(0);
return FALSE;
}
BOOL fState = ReadFile(data.m_pParentData, byteArray.GetData(),
dwLength, &dwLength, &os);
if (!fState)
{
if (GetLastError() != ERROR_IO_PENDING)
{
/// 写失败,且不是由于异步操作在后台进行引起的。
bRes = FALSE;
}
else
{
/// 异步操作在后台进行。
DWORD dwRes = WaitForSingleObject(os.hEvent, INFINITE);
switch(dwRes)
{
/// 重叠操作的事件信号已经被触发了。
case WAIT_OBJECT_0:
{
if (!GetOverlappedResult(data.m_pParentData,
&os, &dwLength, FALSE))
{
bRes = FALSE;
}
else
{
/// 写操作成功。
bRes = TRUE;
}
}break;
default:
{
/// 在等待事件的过程中发生了一个错误。
bRes = FALSE;
}break;
}
}
}
CloseHandle(os.hEvent);
#endif //MCGSSET_ESET
#ifdef MCGS_WCE_EMU
/// 此段暂时不会调用到
#endif //MCGS_WCE_EMU
#ifdef MCGS_WCE
/// 这一段时运行环境下调用的代码
bRes = ReadFile(data.m_pParentData, byteArray.GetData(),
dwLength, &dwLength, NULL);
#endif //MCGS_WCE
}
else
{
return bRes = FALSE;
}
return bRes;
}
/// 函数功能: 用于把CString字符串转化为CByteArry数组。
/// 函数返回: 0,转换出错,其他表示转换的字节数。
/// 参数意义: str 原CString字符串。
/// byte 目标CByteArry数组。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
int CDevServer::SvrStr2Byte(CString &str, CByteArray &byte)
{
byte.SetSize(0);
#ifdef _UNICODE
int nLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
if (nLen == 0)
{
return 0;
}
byte.SetSize(nLen);
if (nLen != WideCharToMultiByte(CP_ACP, 0, str, -1,
(char*)byte.GetData(), nLen, NULL, NULL))
{
byte.SetSize(0);
return 0;
}
byte.SetSize(nLen - 1);
#else
byte.SetSize(str.GetLength());
memcpy(byte.GetData(), (LPCTSTR)str, str.GetLength());
#endif //_UNICODE
return byte.GetSize();
}
/// 函数功能: 用于把CByteArry数组转化为CString字符串。
/// 函数返回: 0,转换出错,其他表示转换的字节数。
/// 参数意义: byte 原CByteArry数组。
/// str 目标CString字符串。
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
int CDevServer::SvrByte2Str(CByteArray &byte, CString &str)
{
#ifdef _UNICODE
byte.SetSize(byte.GetSize() + 1);
byte[byte.GetSize() - 1] = 0;
PWSTR pWideChar;
int nLen = MultiByteToWideChar(CP_ACP, 0,
(char*)byte.GetData(), -1, NULL, 0);
if (nLen == 0)
{
return 0;
}
pWideChar = (PWSTR)HeapAlloc(GetProcessHeap(), 0, nLen*sizeof(WCHAR));
if (pWideChar == NULL)
{
return 0;
}
if (nLen != MultiByteToWideChar(CP_ACP, 0,
(char*)byte.GetData(), -1, pWideChar, nLen))
{
HeapFree(GetProcessHeap(), 0, pWideChar);
return 0;
}
str = pWideChar;
HeapFree(GetProcessHeap(), 0, pWideChar);
#else
byte.SetSize(byte.GetSize() + 1);
byte[byte.GetSize() - 1] = 0;
str = (LPCTSTR)byte.GetData();
#endif //_UNICODE
return byte.GetSize();
}
/// 函数功能: 这个函数用于16进制值传输而不是字符串传输的协议的设备驱动。
/// 把字符串转化为字节型数组。
/// 函数返回: TRUE,正确。FALSE,错误。
/// 参数意义: strProtocol 原字符串。
/// bytArProtocol 目标字节型数组。
///
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
BOOL CDevServer::SvrHStr2HByte(CString& strProtocol, CByteArray& bytArProtocol)
{
int nstrLen = strProtocol.GetLength();
int nBlockLen = 2;
if (nstrLen%nBlockLen != 0 || nstrLen == 0)
{
ASSERT(FALSE);
return FALSE;
}
bytArProtocol.SetSize(nstrLen/2);
for (int i = 0; i < nstrLen; i += nBlockLen)
{
int nData = 0;
_stscanf(strProtocol.Mid(i, 2), _T("%x"), &nData);
bytArProtocol.SetAt(i/2, unsigned char(nData));
}
return TRUE;
}
/// 函数功能: 这个函数用于16进制值传输而不是字符串传输的协议的设备驱动。
/// 把字节型数组转化为字符串。
/// 函数返回: TRUE,正确。FALSE,错误。
/// 参数意义: bytArProtocol 原字节型数组。
/// strProtocol 目标字符串。
///
/// 备 注: 此函数用于提供通用服务,建议不修改。
///
BOOL CDevServer::SvrHByte2HStr(CByteArray& bytArProtocol, CString& strProtocol)
{
strProtocol = _T("");
CString strTemp = _T("");
for (int i = 0; i < bytArProtocol.GetSize(); i ++)
{
strTemp.Format(_T("%.2X"), bytArProtocol.GetAt(i));
strProtocol += strTemp;
}
return TRUE;
}
/// 函数功能: 这个函数用于将从设备读回来的字符串转化为一个 double 型的数值,即一个通道的值。
/// 函数返回: 通道的值。
/// 参数意义: strProtocol 从设备读回来的字符串。
/// nDateType 该通道的数据类型:
/// 0--16: 位操作的位序号。
/// 80: 无符号8位二进制数。
/// 81: 有符号8位二进制数。
/// 82: 8位BCD码。
/// 83: 无符号16位二进制数。
/// 84: 有符号16位二进制数。
/// 85: 16位BCD码。
/// 86: 无符号32位二进制数。
/// 87: 有符号32位二进制数。
/// 88: 32位BCD码。
/// 89: 32位浮点数。
/// 100: ASCII表示的浮点数。
/// nBlockLen 设备中数据通常底位在前,高位在后,这是块长度,
/// 1表示1个字符,通常是4个位。
/// nBytes 位操作的时候他表示字节数,nDataType = 100时他表示要用的字符串长。
/// 其它时候没有意义。
/// 备 注: 此函数用于提供通用服务,建议不修改。
/// 应用举例:strProtocol = _T("2345"),通常这是一个HEX的字符串,即两个字符表示一个字节。
/// 转换时通常nBlockLen = 2,即高位字节在后,地位字节在前
/// 如果nDataType = 85,则结果是4523。如果nDataType = 83,则结果是0X4523。
/// 如果nDataType = 1,nBytes = 2 则结果是1。nDataType = 2 则结果是0。
/// 如果strProtocol = _T("234.56"),nDataType = 100则结果是234.56。
double CDevServer::SvrStr2Double(CString strProtocol,
int nDataType,
int nBlockLen,
int nBytes)
{
double dReturn = 0;
CString strValue = _T("");
/// 这一段获取需要的字符串
{
int nStrLen = 0;
if (nDataType < 16)
{
nStrLen = 2 * nBytes;
}
else if (nDataType >= 80 && nDataType < 89)
{
nStrLen = (int)pow(2, (nDataType - 80)/3 + 1);
}
else if (nDataType == 89)
{
/// 如果是标准浮点数,那么这个字符串的长度必定是8(4个字节)。
nStrLen = 8;
}
else if (nDataType == 100)
{
nStrLen = nBytes;
}
else
{
ASSERT(FALSE);
}
strValue = strProtocol.Left(nStrLen);
if (nBlockLen > 0)
{
CString strTemp = strValue;
strValue = _T("");
ASSERT(nStrLen%nBlockLen == 0);
for (int i = 0; i < nStrLen; i += nBlockLen)
{
strValue += strTemp.Mid(nStrLen - nBlockLen - i, nBlockLen);
}
}
}
int nData = 0;
if (nDataType < 16)
{
/// 表示这是位操作
_stscanf(strValue, _T("%x"), &nData);
dReturn = (nData>>nBytes)&0x01;
}
else if (nDataType >= 80 && nDataType < 89)
{
switch (nDataType)
{
case 80:
{
_stscanf(strValue, _T("%X"), &nData);
dReturn = (unsigned char)(nData & 0xFF);
}break;
case 81:
{
_stscanf(strValue, _T("%X"), &nData);
dReturn = (signed char)(nData & 0xFF);
}break;
case 82:
{
_stscanf(strValue, _T("%d"), &nData);
dReturn = nData;
}break;
case 83:
{
_stscanf(strValue, _T("%X"), &nData);
dReturn = (unsigned short)(nData & 0xFFFF);
}break;
case 84:
{
_stscanf(strValue, _T("%X"), &nData);
dReturn = (signed short)(nData & 0xFFFF);
}break;
case 85:
{
_stscanf(strValue, _T("%d"), &nData);
dReturn = nData;
}break;
case 86:
{
_stscanf(strValue, _T("%X"), &nData);
dReturn = (DWORD)nData;
}break;
case 87:
{
_stscanf(strValue, _T("%X"), &nData);
dReturn = nData;
}break;
case 88:
{
_stscanf(strValue, _T("%d"), &nData);
dReturn = nData;
}break;
}
}
else if (nDataType == 89)
{
/// 如果是标准浮点数,那么这个字符串的长度必定是8(4个字节)。
unsigned char cf[4];
for (int i = 0; i < 4; i ++)
{
_stscanf(strValue.Mid(2 * i, 2), _T("%x"), &nData);
cf[i] = nData;
}
float f = 0;
CopyMemory(&f, cf, 4);
dReturn = f;
}
else if (nDataType == 100)
{
float fData = 0;
_stscanf(strValue, _T("%f"), &fData);
dReturn = fData;
}
else
{
ASSERT(FALSE);
}
return dReturn;
}
/// 函数功能: 这个函数用于将一个 double 型的数值(即一个通道的值)转化为要写到设备的字符串。
/// 函数返回: 要写到设备的字符串。
/// 参数意义: dData 一个 double 型的数值(即一个通道的值)。
/// nDataType 该通道的数据类型:
/// 80: 无符号8位二进制数。
/// 81: 有符号8位二进制数。
/// 82: 8位BCD码。
/// 83: 无符号16位二进制数。
/// 84: 有符号16位二进制数。
/// 85: 16位BCD码。
/// 86: 无符号32位二进制数。
/// 87: 有符号32位二进制数。
/// 88: 32位BCD码。
/// 89: 32位浮点数。
/// 100: ASCII表示的浮点数。
/// nBlockLen 设备中数据通常底位在前,高位在后,这是块长度,1表示1个字符即4个位。
/// nStrLen 要产生的字符串的长度。
/// 备 注: 此函数用于提供通用服务,建议不修改。此函数功能和上一个函数相反。
///
CString CDevServer::SvrDouble2Str(double dData,
int nDataType,
int nBlockLen,
int nStrLen)
{
if (nDataType >= 80 && nDataType < 89)
{
nStrLen = (int)pow(2, (nDataType - 80)/3 + 1);
}
else if (nDataType == 89)
{
/// 如果是标准浮点数,那么这个字符串的长度必定是8(4个字节)。
nStrLen = 8;
}
else if (nDataType == 100)
{
;
}
else
{
ASSERT(FALSE);
}
CString strFormat = _T("");
strFormat.Format(_T("%%.%d"), nStrLen);
CString strValue = _T("");
if (nDataType >= 80 && nDataType < 89)
{
DWORD dwValue = 0;
switch (nDataType)
{
case 80:
{
dwValue =(DWORD)((unsigned char)(dData));
strFormat += _T("X");
}break;
case 81:
{
dwValue =(DWORD)((signed char)(dData));
strFormat += _T("X");
}break;
case 82:
{
dwValue =(DWORD)((unsigned char)(dData));
strFormat += _T("d");
}break;
case 83:
{
dwValue =(DWORD)((unsigned short)(dData));
strFormat += _T("X");
}break;
case 84:
{
dwValue =(DWORD)((signed short)(dData));
strFormat += _T("X");
}break;
case 85:
{
dwValue =(DWORD)((unsigned short)(dData));
strFormat += _T("d");
}break;
case 86:
{
dwValue =(DWORD)(dData);
strFormat += _T("X");
}break;
case 87:
{
dwValue =(DWORD)((int)(dData));
strFormat += _T("X");
}break;
case 88:
{
dwValue =(DWORD)(dData);
strFormat += _T("d");
}break;
}
strValue.Format(strFormat, dwValue);
}
else if (nDataType == 89)
{
/// 如果是标准浮点数,那么这个字符串的长度必定是8(4个字节)。
float f = float(dData);
unsigned char cf[4];
CopyMemory(cf, &f, 4);
CString strTemp = _T("");
for (int i = 0; i < 4; i ++)
{
strTemp.Format(_T("%.2x"), cf[i]);
strValue += strTemp;
}
}
else if (nDataType == 100)
{
strFormat.Format(_T("%%%d.%df"), nStrLen, nBlockLen);
strValue.Format(strFormat, dData);
}
strValue = strValue.Right(nStrLen);
CString strProtocol = _T("");
if (nBlockLen > 0 && nDataType != 100)
{
for (int i = 0; i < nStrLen; i += nBlockLen)
{
strProtocol += strValue.Mid(nStrLen - nBlockLen- i, nBlockLen);
}
}
else
{
strProtocol = strValue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -