📄 hwmobile.cpp
字号:
// 输出字符串加个结束符
*szDst = '\0';
// 返回目标字符串长度
return nDstLength;
}
//
// 7bit编码
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: szDst - 目标编码串指针
// 返回: 目标编码串长度
//
int CHwMobile::gsmEncode7bit(const char *pSrc, BYTE *szDst, int nSrcLength, int nDstSize)
{
int nSrc=0; // 源字符串的计数值
int nDst=0; // 目标编码串的计数值
int nChar=0; // 当前正在处理的组内字符字节的序号,范围是0-7
BYTE nLeft=0; // 上一字节残余的数据
char *pDstTail = (char *)(szDst + nDstSize);
// 计数值初始化
nSrc = 0;
nDst = 0;
// 将源串每8个字节分为一组,压缩成7个字节
// 循环该处理过程,直至源串被处理完
// 如果分组不到8字节,也能正确处理
while (nSrc < nSrcLength)
{
// 取源字符串的计数值的最低3位
nChar = nSrc & 7;
// 处理源串的每个字节
if(nChar == 0)
{
// 组内第一个字节,只是保存起来,待处理下一个字节时使用
nLeft = *pSrc;
}
else
{
// 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节
*szDst = (*pSrc << (8-nChar)) | nLeft;
// 将该字节剩下的左边部分,作为残余数据保存起来
nLeft = *pSrc >> nChar;
// 修改目标串的指针和计数值
szDst++;
if ( (char*)szDst >= pDstTail ) break;
nDst++;
}
// 修改源串的指针和计数值
pSrc++;
nSrc++;
}
// 返回目标串长度
return nDst;
}
// 7bit解码
// 输入: pSrc - 源编码串指针
// nSrcLength - 源编码串长度
// 输出: szDst - 目标字符串指针
// 返回: 目标字符串长度
int CHwMobile::gsmDecode7bit(const BYTE* pSrc, char* szDst, int nSrcLength, int nDstSize)
{
int nSrc=0; // 源字符串的计数值
int nDst=0; // 目标解码串的计数值
int nByte=0; // 当前正在处理的组内字节的序号,范围是0-6
BYTE nLeft=0; // 上一字节残余的数据
char *pDstTail = (char *)(szDst + nDstSize);
// 计数值初始化
nSrc = 0;
nDst = 0;
// 组内字节序号和残余数据初始化
nByte = 0;
nLeft = 0;
// 将源数据每7个字节分为一组,解压缩成8个字节
// 循环该处理过程,直至源数据被处理完
// 如果分组不到7字节,也能正确处理
while(nSrc<nSrcLength)
{
// 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节
*szDst = ((*pSrc << nByte) | nLeft) & 0x7f;
// 将该字节剩下的左边部分,作为残余数据保存起来
nLeft = *pSrc >> (7-nByte);
// 修改目标串的指针和计数值
szDst++;
if ( (char*)szDst >= pDstTail ) break;
nDst++;
// 修改字节计数值
nByte++;
// 到了一组的最后一个字节
if(nByte == 7)
{
// 额外得到一个目标解码字节
*szDst = nLeft;
// 修改目标串的指针和计数值
szDst++;
if ( (char*)szDst >= pDstTail ) break;
nDst++;
// 组内字节序号和残余数据初始化
nByte = 0;
nLeft = 0;
}
// 修改源串的指针和计数值
pSrc++;
nSrc++;
}
// 输出字符串加个结束符
*szDst = '\0';
// 返回目标串长度
return nDst;
}
//
// UCS2编码
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: szDst - 目标编码串指针
// 返回: 目标编码串长度
//
int CHwMobile::gsmEncodeUcs2(const char *pSrcByte, BYTE *szDst, int nSrcLength, int nDstSize, WCHAR *wzSrc/*=NULL*/ )
{
int nDstLength=0; // UNICODE宽字符数目
WCHAR wchar[1024] = {0}; // UNICODE串缓冲区
char *pDstTail = (char *)(szDst + nDstSize);
// 字符串-->UNICODE串
if ( wzSrc )
nDstLength = (int)wcslen ( wzSrc );
if ( nDstLength <= 0 )
{
nDstLength = MultiByteToWideChar(CP_ACP, 0, pSrcByte, nSrcLength, wchar, 1024);
wzSrc = wchar;
}
// 高低字节对调,输出
for(int i=0; i<nDstLength; i++)
{
*szDst++ = wzSrc[i] >> 8; // 先输出高位字节
if ( (char*)szDst >= pDstTail ) break;
*szDst++ = wzSrc[i] & 0xff; // 后输出低位字节
if ( (char*)szDst >= pDstTail ) break;
}
// 返回目标编码串长度
return nDstLength * 2;
}
// UCS2解码
// 输入: pSrc - 源编码串指针
// nSrcLength - 源编码串长度
// 输出: szDst - 目标字符串指针
// 返回: 目标字符串长度
int CHwMobile::gsmDecodeUcs2(
const BYTE* pSrc,
char* szDst,
int nSrcLength,
int nDstSize,
WCHAR* wzSMSContent_Wide/*=NULL*/,
int nWideSize/*=0*/
)
{
WCHAR wchar[1024] = {0}; // UNICODE串缓冲区
ASSERT ( szDst );
memset ( szDst, 0, nDstSize );
// 源数据长度必须是2的倍数
int nModLength = (nSrcLength%2);
int nValidSrcLength = nSrcLength + nModLength;
nValidSrcLength = MIN(nValidSrcLength,1024*2);
BYTE *pSrcValid = new BYTE[nValidSrcLength];
if ( !pSrcValid ) return -1;
memset ( pSrcValid, 0, nValidSrcLength );
memcpy ( pSrcValid + nModLength, pSrc, nSrcLength );
// 高低字节对调,拼成UNICODE
for ( int i=0; i<nValidSrcLength/2; i++ )
{
wchar[i] = pSrcValid[2*i] << 8; // 先高位字节
wchar[i] |= pSrcValid[2*i+1]; // 后低位字节
}
delete[] pSrcValid;
if ( wzSMSContent_Wide && nWideSize > 0 )
{
wcsncpy ( wzSMSContent_Wide, wchar, nWideSize );
}
// UNICODE串-->字符串,因为不知道源字符串到底是GB还是Big5,所以用两种方式分别给于解码,解码后的结果再来取舍
// 取面包含问号少的那个
char szDestTemp1[4096] = {0}, szDestTemp2[4096] = {0};
int nDstLength1 = WideCharToMultiByte ( CHARCODEPAGE_GB, 0, wchar, nValidSrcLength/2, szDestTemp1, 4096, NULL, NULL);
int nQuestionCount1 = CountCharNumber ( szDestTemp1, '?' );
int nDstLength2 = WideCharToMultiByte ( CHARCODEPAGE_BIG5, 0, wchar, nValidSrcLength/2, szDestTemp2, 4096, NULL, NULL);
int nQuestionCount2 = CountCharNumber ( szDestTemp2, '?' );
char *szDestTemp = NULL;
if ( nQuestionCount1 == nQuestionCount2 )
{
// 随机取一个算了
if ( GetTickCount()%2 )
szDestTemp = szDestTemp1;
else
szDestTemp = szDestTemp2;
}
else
{
szDestTemp = ( (nQuestionCount1 < nQuestionCount2) ? szDestTemp1 : szDestTemp2 );
}
return hwSnprintfA ( szDst, nDstSize/sizeof(char), "%s", szDestTemp );
}
//
// 8bit编码
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: szDst - 目标编码串指针
// 返回: 目标编码串长度
//
int CHwMobile::gsmEncode8bit(const char *pSrc, BYTE *szDst, int nSrcLength, int nDstSize)
{
char *pDstTail = (char *)(szDst + nDstSize);
// 简单复制
memcpy(szDst, pSrc, nSrcLength);
return nSrcLength;
}
//
// 8bit解码
// 输入: pSrc - 源编码串指针
// nSrcLength - 源编码串长度
// 输出: szDst - 目标字符串指针
// 返回: 目标字符串长度
//
int CHwMobile::gsmDecode8bit(const BYTE* pSrc, char* szDst, int nSrcLength, int nDstSize)
{
char *pDstTail = (char *)(szDst + nDstSize);
// 简单复制
memcpy(szDst, pSrc, nSrcLength);
// 输出字符串加个结束符
*szDst = '\0';
return nSrcLength;
}
//
// 可打印字符串转换为字节数据
// 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: szDst - 目标数据指针
// 返回: 目标数据长度
//
int CHwMobile::gsmString2Bytes(const char *pSrc, BYTE *szDst, int nSrcLength, int nDstSize)
{
char *pDstTail = (char *)(szDst + nDstSize);
for (int i = 0; i < nSrcLength; i += 2)
{
// 输出高4位
if ((*pSrc >= '0') && (*pSrc <= '9'))
{
*szDst = (*pSrc - '0') << 4;
}
else
{
*szDst = (*pSrc - 'A' + 10) << 4;
}
pSrc++;
// 输出低4位
if ((*pSrc>='0') && (*pSrc<='9'))
{
*szDst |= *pSrc - '0';
}
else
{
*szDst |= *pSrc - 'A' + 10;
}
pSrc++;
szDst++;
if ( (char*)szDst >= pDstTail ) break;
}
// 返回目标数据长度
return (nSrcLength / 2);
}
BOOL CHwMobile::Init ()
{
if ( m_nComNO < 1 || m_nBaudRate < 1 )
return FALSE;
// HwDbgLog ( L_DEBUG, "从 [COM%d] 来打开手机", m_nComNO );
// 打开串口
if ( !OpenCOM ( m_nComNO, m_nBaudRate, TRUE ) )
{
if ( m_nInitOK )
{
Log ( L_WARNING, _T("Open mobile module interface [COM%d] failed"), m_nComNO );
}
m_nInitOK = FALSE;
return FALSE;
}
// 初始化手机模块
if ( !gsmInit() )
{
if ( m_nInitOK )
{
Log ( L_WARNING, _T("Initialize mobile module [COM%d] failed"), m_nComNO );
}
m_nInitOK = FALSE;
return FALSE;
}
m_nInitOK = TRUE;
return TRUE;
}
//
// 初始化GSM状态
//
BOOL CHwMobile::gsmInit()
{
// 测试 GSM-MODEM 的存在性
if ( !QueryExistByRWCmd () )
return FALSE;
// 关闭回显功能
if ( Write ( "ATE0\r" ) < 1 ) return FALSE;
ReadResponse ( "OK" );
// 开启来电显示
if ( Write ( "AT+CLIP=1\r" ) < 1 ) return FALSE;
ReadResponse ( "OK" );
// 设置短信为PDU模式
if ( Write("AT+CMGF=0\r" ) < 1 ) return FALSE;
if ( !ReadResponse ( "OK" ) )
return FALSE;
// 设置短信通知方式为“直接通知TE”
// mode : 2 - 通知TE。在数据线被占用的情况下,先缓冲起来,待数据线空闲,再行通知。
// mt : 2 - 对于class 2,储存到SIM卡,并且向TE发出通知;对于其它class,直接将消息转发到 TE
if ( Write("AT+CNMI=2,2\r" ) < 1 ) return FALSE;
if ( !ReadResponse ( "OK" ) )
{
Log ( L_WARNING | L_OUT_UI, _T("Maybe none SIM card") );
return FALSE;
}
// 设置手机使用的字符集为“UCS2”
if ( Write ( "AT+CSCS=\"UCS2\"\r" ) < 1 )
return FALSE;
if ( !ReadResponse ( "OK\r\n" ) )
return FALSE;
ClearComm ( TRUE );
return TRUE;
}
//
// 读取短信中心号码
//
BOOL CHwMobile::GetSMSCNO ()
{
if ( m_csSMSC.GetLength() > MIN_MOBILENO_LENGTH )
return TRUE;
if ( !m_nInitOK || !m_handleCOM || m_handleCOM == INVALID_HANDLE_VALUE )
return FALSE;
if ( Write ( "AT+CSCA?\r" ) < 1 )
return FALSE;
CString csAns;
char szAns[MAX_COM_BUFSIZE] = {0};
if ( !ReadResponse ( "OK", TRUE, szAns, MAX_COM_BUFSIZE ) )
return FALSE;
csAns = GetCompatibleString ( szAns, FALSE );
LPCTSTR lpszFindStr = _T("+CSCA: \"");
int nFindPos = csAns.Find ( lpszFindStr, 0 );
if ( nFindPos < 0 ) return FALSE;
nFindPos += lstrlen ( lpszFindStr );
csAns = csAns.Mid ( nFindPos );
nFindPos = csAns.Find ( _T("\""), 0 );
if ( nFindPos < 0 ) return FALSE;
csAns = csAns.Left ( nFindPos );
// UCS2解码
char szTempBuf[MAX_COM_BUFSIZE] = {0};
CMultiByteString MultiByteString_Ans(csAns);
int nRet = gsmString2Bytes ( MultiByteString_Ans.GetBuffer(), (BYTE*)szTempBuf, MultiByteString_Ans.GetLength(), sizeof(szTempBuf) ); // 格式转换
char szSMSC[PHONENO_LENGTH] = {0};
gsmDecodeUcs2 ( (BYTE*)szTempBuf, szSMSC, nRet, PHONENO_LENGTH ); // 转换到TP-DU
m_csSMSC = GetCompatibleString ( szSMSC, FALSE );
Log ( L_VERBOSE | L_OUT_UI, _T("Get SMSC : %s"), m_csSMSC );
if ( m_Proc_SaveSMSCFromGSM )
{
m_Proc_SaveSMSCFromGSM ( m_csSMSC );
}
return TRUE;
}
//
// 用命令来从手机中获取一些信息
//
BOOL CHwMobile::DemandMobileInfo ( char *szCmd, OUT CString &csAns )
{
csAns.Empty ();
ClearComm ( TRUE ); ClearComm ( FALSE );
if ( Write ( szCmd ) < 1 )
return FALSE;
char szAns[MAX_COM_BUFSIZE] = {0};
if ( !ReadResponse ( "OK", TRUE, szAns, MAX_COM_BUFSIZE ) )
return FALSE;
csAns = GetCompatibleString(szAns,FALSE);
csAns.ReleaseBuffer ();
csAns.Replace ( _T("OK"), _T("") );
csAns.Remove ( _T('\r') );
csAns.Remove ( _T('\n') );
return TRUE;
}
//
// 从串口中读回应代码, 如果读到的回应代码里能找到字符串 szResponse 就返回“TRUE”
// 否则返回“FALSE”
//
BOOL CHwMobile::ReadResponse ( char* szResponse, BOOL bQuick/*=TRUE*/, char *szAns/*=NULL*/, int nSize/*=0*/ )
{
ASSERT ( szResponse );
int nLen = (int)strlen(szResponse);
ASSERT ( nLen >= 2 );
if ( !WaitForDataToRead ( nLen, bQuick ? WAIT_GSM_DATA_TIME_QUICK : WAIT_GSM_DATA_TIME_SLOW ) )
return FALSE;
char ans[MAX_COM_BUFSIZE+1] = {0}; // 应答串
int nReadLen = Read ( ans, MAX_COM_BUFSIZE );
BOOL bRet = FALSE;
if ( strstr ( ans, szResponse ) )
bRet = TRUE;
if ( nReadLen > 0 && szAns && nSize > 0 )
{
int nLen = MIN ( nReadLen,nSize-1 );
memcpy ( szAns, ans, nLen );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -