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

📄 hwmobile.cpp

📁 基于vc++6.0的收发手机短信、读写手机电话本的平台
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	// 输出字符串加个结束符
	*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 + -