|
@@ -0,0 +1,901 @@
|
|
|
+#include "StdAfx.h"
|
|
|
+#include "SMSProcess.h"
|
|
|
+
|
|
|
+namespace SMSProcess
|
|
|
+{
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ CCommRS232 *_pSMSComm = NULL;
|
|
|
+ CRITICAL_SECTION _csRS232;
|
|
|
+ INT _nMaxSMSChar = 70; // 短信猫一条短信最大支持的字符个数;
|
|
|
+ const INT MAX_SIZE = 512;
|
|
|
+ int g_nCMGFStatus = 0;//保存现在的传输格式 发送短信用0 接收短信用1;
|
|
|
+
|
|
|
+ HANDLE _hSMSReceiveThread = NULL;
|
|
|
+ HANDLE _hCtrlEvent = NULL;
|
|
|
+
|
|
|
+ int g_nMakeCall = 0; // 发送后是否先拔打电话提醒
|
|
|
+
|
|
|
+ PFCALLBACK gEnalbeAlarmCallBack = NULL;
|
|
|
+#define PDU_MAXNUMLEN 70 // 最大号码长度;
|
|
|
+#define PDU_MAXUNICODELEN 70 // pdu Unicode的最大长度;
|
|
|
+#define NUM_NAT 0x81 // 非国际号码前缀 phone number type for non- '+'(national) numbers
|
|
|
+#define NUM_INT 0x91 // 国际号码前缀 phone number type for numbers prefixed by '+'(international)
|
|
|
+
|
|
|
+ //--------------------------------------------------------------------------------
|
|
|
+ // FOR gsm sms
|
|
|
+#define GSM_MAX_WAIT_TIME 12000 //发送短消息时的最长等待时间
|
|
|
+#define GSM_RESPONSE_NORESPONSE 0 //无响应
|
|
|
+#define GSM_RESPONSE_OK 1 //正确返回
|
|
|
+#define GSM_RESPONSE_ERROR 2 //返回错误信息,含错误代码
|
|
|
+#define GSM_RESPONSE_UNKNOWN 3 //返回无法确定的信息
|
|
|
+#define GSM_CMS_ERROR 0 //CMS Error -- Message service error
|
|
|
+#define GSM_CME_ERROR 1 //CME Error
|
|
|
+#define NOP 183 //非可见字符
|
|
|
+
|
|
|
+#define MAX_WRITE_STR_LEN 3840
|
|
|
+#define MAX_READ_STR_LEN 512//256
|
|
|
+#define MIN_READ_STR_LEN 6
|
|
|
+#define MAX_TMPSTR_LEN 512//256
|
|
|
+
|
|
|
+ void SwapChars(IN OUT TCHAR *szNumber);
|
|
|
+ char ACharToBChar(char c);
|
|
|
+ CString DeleteEnterForStr(CString sData);
|
|
|
+ int MyCharCount(const char* szMsg);
|
|
|
+ INT Str2PDU_Unicode(const TCHAR *szMsg, TCHAR *szPDU);
|
|
|
+ BOOL GetValidResponse(const TCHAR *szBuff, int nCount, TCHAR *szResponse);
|
|
|
+ int GSMResponse(const TCHAR *szBuff, int nCount, int &nErrorType, int &nErrorCode);
|
|
|
+ int SendSMS(const char *szNo, const char *szMsg, char* szEvent);
|
|
|
+ int ReceiveSms(int iIndex, char* strTelFrom, char* strTime, char* strReceiveMsg, int nCharSize);
|
|
|
+ char* PickSegTxt(const char* pMsgAll, char* szSeg, int nSize);
|
|
|
+ void TransformPDUPhone(IN CONST TCHAR *szPhone, OUT TCHAR* szPDUPhone, IN CONST INT& nPDUPhoneLen);
|
|
|
+ void TransformPDUMsg(IN CONST TCHAR *szPhone, IN CONST TCHAR* szMsg, IN BOOL bNeedReport, OUT TCHAR* szPduContent, IN CONST INT& nContLen);
|
|
|
+ DWORD WINAPI SMSReceiveThread(LPVOID lpParameter);
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:SwapChars[2/22/2016 IT];
|
|
|
+ /* 描述:奇数位和偶数位字符交换( 13823652665F --> 3128632566F5, 用于电话号码编码);
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN]szTelNumber:需要转换的电话号码;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void SwapChars(IN OUT TCHAR *szTelNumber)
|
|
|
+ {
|
|
|
+ if (szTelNumber == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ TCHAR ch;
|
|
|
+ INT nLength = (INT)_tcslen(szTelNumber);
|
|
|
+ for (INT nIndex = 0; nIndex < nLength - 1; nIndex += 2)
|
|
|
+ {
|
|
|
+ ch = szTelNumber[nIndex];
|
|
|
+ szTelNumber[nIndex] = szTelNumber[nIndex + 1];
|
|
|
+ szTelNumber[nIndex + 1] = ch;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:TransformPDUPhone[2/22/2016 IT];
|
|
|
+ /* 描述:将电话号码转换为GSM PDU格式;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN]szPhone:需要转换的电话号码;
|
|
|
+ /* [OUT]szPDUPhone:转换后的PDU电话号码;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void TransformPduTelNumber(IN CONST TCHAR *szTelNumber, OUT TCHAR* szPduTelNumber, IN CONST INT& nPduTelNumber)
|
|
|
+ {
|
|
|
+ if (szTelNumber == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (szPduTelNumber == NULL || nPduTelNumber == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ INT nType = 0;
|
|
|
+ TCHAR szTemp[PDU_MAXNUMLEN] = { 0 };
|
|
|
+ INT nLen = (INT)_tcslen(szTelNumber);
|
|
|
+
|
|
|
+ if (szTelNumber[0] == _T('+'))
|
|
|
+ {
|
|
|
+ _tcsncpy_s(szTemp, szTelNumber + 1, PDU_MAXNUMLEN);
|
|
|
+ nType = NUM_INT;
|
|
|
+ nLen--;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tcsncpy_s(szTemp, szTelNumber, PDU_MAXNUMLEN);
|
|
|
+ nType = NUM_NAT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_tcslen(szTemp) % 2)
|
|
|
+ {
|
|
|
+ _tcscat_s(szTemp, _T("F"));
|
|
|
+ }
|
|
|
+
|
|
|
+ SwapChars(szTemp);
|
|
|
+
|
|
|
+ _stprintf_s(szPduTelNumber, nPduTelNumber, _T("%02X%02X%s"), nLen, nType, szTemp);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:TransformPDUMsg[2/22/2016 IT];
|
|
|
+ /* 描述:将短消息(包括电话号码、文本)转换为GSM PDU格式;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN]szPhone :需要转换的电话号码;
|
|
|
+ /* [IN]szMsg :需要转换的短信消息文本;
|
|
|
+ /* [IN] bNeedReport:是否需要提供信息报告;
|
|
|
+ /* [OUT] szPduContent:转换后的GSM PDU文本;
|
|
|
+ /* [IN] nContLen:szPduContent缓冲区大小;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void TransformPduMsg(IN CONST TCHAR *szTelNumber, IN CONST TCHAR* szMsg, IN BOOL bNeedReport, OUT TCHAR* szPduContent, IN CONST INT& nContLen)
|
|
|
+ {
|
|
|
+ INT nType = 0;
|
|
|
+ INT nCodingScheme = 0;
|
|
|
+
|
|
|
+ TCHAR szPduTelNumber[PDU_MAXNUMLEN] = { 0 };
|
|
|
+ TransformPduTelNumber(szTelNumber, szPduTelNumber, PDU_MAXNUMLEN);
|
|
|
+
|
|
|
+ nType = 0X10 + 0X01; // 0x11 -- 0001 0001;
|
|
|
+ if (bNeedReport)
|
|
|
+ {
|
|
|
+ nType += 0X20; // 0x20 -- 0010 0000;
|
|
|
+ }
|
|
|
+
|
|
|
+ nCodingScheme = 0X08; // 0x08 -- 0000 1000 -- 16bit UCS2;
|
|
|
+ TCHAR szPduMsg[1024] = { 0 };
|
|
|
+ Str2PDU_Unicode(szMsg, szPduMsg);
|
|
|
+
|
|
|
+ _stprintf_s(szPduContent, nContLen, _T("00%02X00%s00%02X00%02X%s"),
|
|
|
+ //00 - 默认短消息中心;
|
|
|
+ nType,// FO;
|
|
|
+ //00 - TP-MO;
|
|
|
+ szPduTelNumber,
|
|
|
+ //00 - TP-PID;
|
|
|
+ nCodingScheme,
|
|
|
+ //00 - TP-VP;
|
|
|
+ _tcslen(szPduMsg) / 2,
|
|
|
+ szPduMsg);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:Str2PDU_Unicode[2/22/2016 IT];
|
|
|
+ /* 描述:将普通文本转换为gsm需要的unicode编码格式(可用于中、英文模式);
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] szMsg:需要转换的字符串文本;
|
|
|
+ /* [OUT] szPDU:转换后的pdu unicode文本;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:int <=0 表示转换失败,否则为unicode字符长度;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ INT Str2PDU_Unicode(IN CONST TCHAR *szMsg, TCHAR *szPDU)
|
|
|
+ {
|
|
|
+ WCHAR wszPDU[PDU_MAXUNICODELEN];
|
|
|
+
|
|
|
+ int nCount = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szMsg, (int)_tcslen(szMsg), wszPDU, PDU_MAXUNICODELEN);
|
|
|
+ if (nCount < 1)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < nCount; i++)
|
|
|
+ {
|
|
|
+ wsprintf(szPDU + i * 4, _T("%4.4X"), wszPDU[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return nCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:GSMResponse[2/22/2016 IT];
|
|
|
+ /* 描述:根据GSM模块返回的数据判断GSM模块当前的状态;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] szBuff:串口收到的数据;
|
|
|
+ /* [IN] nCount:数据的个数;
|
|
|
+ /* [OUT] nErrorType:如果返回错误信息,返回的错误类型 0 - CME error, 1 - CMS error;
|
|
|
+ /* [OUT] nErrorCode:如果返回错误信息,返回的错误代码;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:int
|
|
|
+ /* GSM_RESPONSE_NORESPONSE 0 //无响应;
|
|
|
+ /* GSM_RESPONSE_OK 1 //正确返回
|
|
|
+ /* GSM_RESPONSE_ERROR 2 //返回错误信息,含错误代码
|
|
|
+ /* GSM_RESPONSE_UNKNOWN 3 //返回无法确定的信息
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ int GSMResponse(const char *szBuff, int nCount, int &nErrorType, int &nErrorCode)
|
|
|
+ {
|
|
|
+ if (nCount == 0)
|
|
|
+ {
|
|
|
+ return GSM_RESPONSE_NORESPONSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nCount < MIN_READ_STR_LEN)
|
|
|
+ {
|
|
|
+ return GSM_RESPONSE_UNKNOWN;
|
|
|
+ }
|
|
|
+
|
|
|
+ char szResponse[MAX_TMPSTR_LEN];
|
|
|
+
|
|
|
+ //获取信息正文
|
|
|
+ if (!GetValidResponse(szBuff, nCount, szResponse))
|
|
|
+ {
|
|
|
+ return GSM_RESPONSE_UNKNOWN;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (szResponse[0] == 'O' && szResponse[1] == 'K' || strstr(szBuff, "OK") != NULL)
|
|
|
+ {
|
|
|
+ return GSM_RESPONSE_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (szResponse[5] == 'E' &&
|
|
|
+ szResponse[6] == 'R' &&
|
|
|
+ szResponse[7] == 'R' &&
|
|
|
+ szResponse[8] == 'O' &&
|
|
|
+ szResponse[9] == 'R')
|
|
|
+ {
|
|
|
+ //Get error type
|
|
|
+ if (szResponse[3] == 'E')
|
|
|
+ {
|
|
|
+ nErrorType = GSM_CME_ERROR;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nErrorType = GSM_CMS_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ //get error code
|
|
|
+ TCHAR szErrorCode[8];
|
|
|
+ _tcsncpy_s(szErrorCode, szResponse + 12, strlen(szResponse) - 12);
|
|
|
+ szErrorCode[strlen(szResponse) - 12] = '\0';
|
|
|
+ nErrorCode = atoi(szErrorCode);
|
|
|
+
|
|
|
+ return GSM_RESPONSE_ERROR;
|
|
|
+ }// end if (szResponse...)
|
|
|
+
|
|
|
+ return GSM_RESPONSE_UNKNOWN;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:GetValidResponse[2/22/2016 IT];
|
|
|
+ /* 描述:对串口返回的数据进行处理 1.判断是否有效 2.去掉首尾多余信息 3.返回有意义的数据;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] szBuff:串口收到的数据;
|
|
|
+ /* [IN] nCount:数据的个数;
|
|
|
+ /* [OUT] szResponse:返回的(关键)正文信息;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:BOOL 成功为TRUE,否则FALSE;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL GetValidResponse(const char *szBuff, int nCount, char *szResponse)
|
|
|
+ {
|
|
|
+ if (nCount < 6)
|
|
|
+ {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // if ( szBuff[nCount-1] != 0x0A ||
|
|
|
+ // szBuff[nCount-2] != 0x0D )
|
|
|
+ // {
|
|
|
+ // return FALSE;
|
|
|
+ // }
|
|
|
+
|
|
|
+ INT i = 0;
|
|
|
+ for (i = nCount - 3; i > 0; i--)
|
|
|
+ {
|
|
|
+ if (szBuff[i] == 0x0A && szBuff[i - 1] == 0x0D)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }//end if
|
|
|
+ }//end for
|
|
|
+
|
|
|
+ if (i < 1)
|
|
|
+ {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ strncpy(szResponse, szBuff + i + 1, nCount - 2 - (i + 1)); // _tcsncpy_s
|
|
|
+ szResponse[nCount - 2 - (i + 1)] = '\0';
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ //============================================================================================
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ int SendSMS(const char *szNo, const char *szMsg, char* szEvent)
|
|
|
+ {
|
|
|
+ EnterCriticalSection(&_csRS232);
|
|
|
+ if (g_nCMGFStatus == 1)
|
|
|
+ {// 如果是TEXT模式,改中PDU模式;
|
|
|
+ char szBuf[MAX_SIZE] = { 0 };
|
|
|
+ g_nCMGFStatus = 0;
|
|
|
+ strcpy(szBuf, "AT+CMGF=0\r");
|
|
|
+ int nLen = _pSMSComm->Write((BYTE *)szBuf, (int)strlen(szBuf));
|
|
|
+ nLen = _pSMSComm->Read((BYTE *)szBuf, MAX_SIZE - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ char WriteBuff[MAX_WRITE_STR_LEN + 1] = { 0 };
|
|
|
+ char ReadBuff[MAX_READ_STR_LEN + 1] = { 0 };
|
|
|
+ int iOffset = 0;
|
|
|
+ int iDataLength = 0;
|
|
|
+ char szTmp[MAX_TMPSTR_LEN + 1] = { 0 };
|
|
|
+ int nTmp;
|
|
|
+
|
|
|
+ char szPDU[512];
|
|
|
+ TransformPduMsg(szNo, szMsg, FALSE, szPDU, 512);
|
|
|
+
|
|
|
+ sprintf(WriteBuff, "AT+CMGS=");
|
|
|
+ iOffset += 8;
|
|
|
+ sprintf(WriteBuff + iOffset, "%03d", strlen(szPDU) / 2 - 1);
|
|
|
+ iOffset = (int)strlen(WriteBuff);
|
|
|
+ WriteBuff[iOffset] = 0x0d;
|
|
|
+ iOffset++;
|
|
|
+
|
|
|
+ //LOG4C_HEX_DUMP((LOG_NOTICE, WriteBuff, iOffset));
|
|
|
+ INT nReturnSize = _pSMSComm->Write((BYTE*)WriteBuff, iOffset);
|
|
|
+ nReturnSize = _pSMSComm->Read((BYTE*)szTmp, MAX_READ_STR_LEN);
|
|
|
+ //LOG4C_HEX_DUMP((LOG_NOTICE, szTmp, nReturnSize));
|
|
|
+
|
|
|
+ iOffset = 0;
|
|
|
+ sprintf(WriteBuff + iOffset, szPDU);
|
|
|
+ iOffset += (int)strlen(szPDU);
|
|
|
+ WriteBuff[iOffset++] = 0x1a;
|
|
|
+ //LOG4C_HEX_DUMP((LOG_NOTICE, WriteBuff, iOffset));
|
|
|
+ nReturnSize = _pSMSComm->Write((BYTE*)WriteBuff, iOffset);
|
|
|
+
|
|
|
+ int nErrorType, nErrorCode; //发送错误类型、编码
|
|
|
+ int nResponse = GSM_RESPONSE_NORESPONSE; //发送结果
|
|
|
+ Sleep(3000);//发送完短信时等待3秒发送
|
|
|
+ do
|
|
|
+ {
|
|
|
+ nTmp = _pSMSComm->Read((BYTE*)szTmp, MAX_READ_STR_LEN);
|
|
|
+ //LOG4C_HEX_DUMP((LOG_NOTICE, szTmp, nTmp));
|
|
|
+ if (nTmp > 0 && iDataLength < MAX_READ_STR_LEN)
|
|
|
+ {
|
|
|
+ strncpy(ReadBuff + iDataLength, szTmp, nTmp);
|
|
|
+ iDataLength += nTmp;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ } while (1);
|
|
|
+ nResponse = GSMResponse(ReadBuff, iDataLength, nErrorType, nErrorCode);
|
|
|
+
|
|
|
+ switch (nResponse)
|
|
|
+ {
|
|
|
+ case GSM_RESPONSE_OK:
|
|
|
+ sprintf(szEvent, "Send OK!");
|
|
|
+ //LOG4C_NO_FILENUM((LOG_NOTICE,"发送结果:%s", szEvent))
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+ case GSM_RESPONSE_NORESPONSE:
|
|
|
+ sprintf(szEvent, "GSM Modem No Response! Please Check The Connection!");
|
|
|
+ //LOG4C_NO_FILENUM((LOG_NOTICE,"发送结果:%s", szEvent))
|
|
|
+ return ERR_CODE_SMS_GSM_NO_RESPONSE;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case GSM_RESPONSE_ERROR:
|
|
|
+ sprintf(szEvent, "Send fail! The card maybe has little money, Please recharge!");
|
|
|
+ //LOG4C_NO_FILENUM((LOG_NOTICE,"发送结果:%s", szEvent))
|
|
|
+ return ERR_CODE_SMS_GSM_ERROR_RESPONSE;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case GSM_RESPONSE_UNKNOWN:
|
|
|
+ sprintf(szEvent, "Send Timeout. The Message may Send OK!");
|
|
|
+ //LOG4C_NO_FILENUM((LOG_NOTICE,"发送结果:%s", szEvent))
|
|
|
+ return ERR_CODE_SMS_GSM_UNKOWN_RESPONSE;
|
|
|
+ default:
|
|
|
+ sprintf(szEvent, "Send Timeout. The Message may Send OK!");
|
|
|
+ //LOG4C_NO_FILENUM((LOG_NOTICE,"发送结果:%s", szEvent))
|
|
|
+ return ERR_CODE_SMS_GSM_UNKOWN_RESPONSE;
|
|
|
+ }//end switch
|
|
|
+
|
|
|
+
|
|
|
+ LeaveCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ return ERR_CODE_SMS_GSM_UNKOWN_RESPONSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ int ReceiveSms(int iIndex, char* strTelFrom, char* strTime, char* strReceiveMsg, int nCharSize)
|
|
|
+ {
|
|
|
+ EnterCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ int nRet = -1;//0:关闭报警 1:恢复正常
|
|
|
+ int nLen = 0;
|
|
|
+ char szBuf[MAX_SIZE] = { 0 };
|
|
|
+ //
|
|
|
+ if (g_nCMGFStatus == 0)
|
|
|
+ {
|
|
|
+ g_nCMGFStatus = 1;
|
|
|
+ strcpy(szBuf, "AT+CMGF=1\r");
|
|
|
+ nLen = _pSMSComm->Write((BYTE *)szBuf, (int)strlen(szBuf));
|
|
|
+ nLen = _pSMSComm->Read((BYTE *)szBuf, MAX_SIZE - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ sprintf(szBuf, "AT+CMGR=%d\r", iIndex);
|
|
|
+ nLen = _pSMSComm->Write((BYTE *)szBuf, (int)strlen(szBuf));
|
|
|
+ nLen = _pSMSComm->Read((BYTE *)szBuf, 511);
|
|
|
+
|
|
|
+ if (nLen < 50)//没有短信
|
|
|
+ {
|
|
|
+ LeaveCriticalSection(&_csRS232);
|
|
|
+ return nRet;
|
|
|
+ }
|
|
|
+
|
|
|
+ CString str;
|
|
|
+
|
|
|
+ int nReaded = 0;
|
|
|
+ int nTelServiceType = 0x91;
|
|
|
+ int nTelType = 0x91;
|
|
|
+ char szTelService[512] = { 0 };
|
|
|
+ char szTel[512] = { 0 };
|
|
|
+ char szTime[512] = { 0 };
|
|
|
+ char szWideBuf[512] = { 0 };
|
|
|
+ char szReceiAscii[512] = { 0 };
|
|
|
+ char *pData = strstr(szBuf, "+CMGR:");
|
|
|
+ char *pOK = strstr(szBuf, "\r\nOK\r\n");
|
|
|
+ if (pData != NULL && pOK != NULL && pOK > pData)
|
|
|
+ {
|
|
|
+ //pOK[0] = 0;
|
|
|
+ memset(pOK, 0, strlen("\r\nOK\r\n"));
|
|
|
+ char* pTemp = pData + 6;//strlen("+CMGR:") = 6;
|
|
|
+ nReaded = atoi(pTemp);//短信已读取标志和类型
|
|
|
+ pTemp = strstr(pTemp, "\r\n");
|
|
|
+ str.Format("%s", pTemp);
|
|
|
+
|
|
|
+ str = DeleteEnterForStr(str);
|
|
|
+ str = str.MakeLower();
|
|
|
+
|
|
|
+ if (str == "open")
|
|
|
+ nRet = 1;
|
|
|
+ if (str == "close")
|
|
|
+ nRet = 0;
|
|
|
+ }
|
|
|
+ //清除
|
|
|
+ //if(strlen(strTelFrom) > 0)
|
|
|
+ {
|
|
|
+ sprintf(szBuf, "AT+CMGD=%d\r", iIndex);
|
|
|
+ nLen = _pSMSComm->Write((BYTE *)szBuf, (int)strlen(szBuf));
|
|
|
+ nLen = _pSMSComm->Read((BYTE *)szBuf, MAX_SIZE - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ LeaveCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ return nRet;//return strlen(strTelFrom) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ DWORD WINAPI SMSReceiveThread(LPVOID lpParameter)
|
|
|
+ {
|
|
|
+ do
|
|
|
+ {
|
|
|
+ char sTelFrom[MAX_SIZE], sTime[MAX_SIZE], sReceiveMsg[MAX_SIZE];
|
|
|
+ int nRet = ReceiveSms(1, sTelFrom, sTime, sReceiveMsg, MAX_SIZE);
|
|
|
+ if (nRet == 1)
|
|
|
+ {
|
|
|
+ gEnalbeAlarmCallBack(nRet);
|
|
|
+ }
|
|
|
+ else if (nRet == 0)
|
|
|
+ {
|
|
|
+ gEnalbeAlarmCallBack(nRet);
|
|
|
+ }
|
|
|
+
|
|
|
+ } while (WaitForSingleObject(_hCtrlEvent, 2000L) == WAIT_TIMEOUT);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ //删除字符串中的换行
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ CString DeleteEnterForStr(CString sData)
|
|
|
+ {
|
|
|
+ CString sRet;
|
|
|
+
|
|
|
+ int iLen = sData.GetLength();
|
|
|
+ char* pc = new char[iLen];
|
|
|
+ memset(pc, 0, iLen);
|
|
|
+ int j = 0;
|
|
|
+ for (int i = 0; i < iLen; i++)
|
|
|
+ {
|
|
|
+ if ((sData[i] == 0x0D) || (sData[i] == 0x0A))
|
|
|
+ continue;
|
|
|
+ pc[j++] = sData[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ sRet.Format("%s", pc);
|
|
|
+ delete[] pc;
|
|
|
+
|
|
|
+ return sRet;
|
|
|
+ }
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ int MyCharCount(const char* szMsg)
|
|
|
+ {
|
|
|
+ int i = 0;
|
|
|
+ int nCharCount = 0;
|
|
|
+ while (szMsg[i] != 0)
|
|
|
+ {
|
|
|
+ if (szMsg[i] & 0x80)
|
|
|
+ {
|
|
|
+ ASSERT(szMsg[i + 1] & 0x80);
|
|
|
+ if (szMsg[i + 1] & 0x80)
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ i++;
|
|
|
+ nCharCount++;
|
|
|
+ }
|
|
|
+ return nCharCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ char ACharToBChar(char c)
|
|
|
+ {
|
|
|
+ if (c >= '0' && c <= '9')
|
|
|
+ c = c - '0';
|
|
|
+ else if (c >= 'A' && c <= 'F')
|
|
|
+ c = c - 'A' + 10;
|
|
|
+ else if (c >= 'a' && c <= 'f')
|
|
|
+ c = c - 'a' + 10;
|
|
|
+ return c;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[2/22/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ char* PickSegTxt(const char* pMsgAll, char* szSeg, int nSize)
|
|
|
+ {
|
|
|
+ char* pRtn = NULL;
|
|
|
+ int i = 0;
|
|
|
+ int nCharCount = 0;
|
|
|
+ while (pMsgAll[i] != 0)
|
|
|
+ {
|
|
|
+ if (pMsgAll[i] & 0x80)
|
|
|
+ {
|
|
|
+ ASSERT(pMsgAll[i + 1] & 0x80);
|
|
|
+ if (pMsgAll[i + 1] & 0x80)
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ i++;
|
|
|
+ nCharCount++;
|
|
|
+ if (pMsgAll[i] == 0 || //已经到了结束符
|
|
|
+ nCharCount == nSize || //大小已经达到
|
|
|
+ nCharCount == nSize - 1 && (pMsgAll[i] & 0x80)) //或者只差最后一个字节并且后续的一个字节为汉字
|
|
|
+ {
|
|
|
+ memcpy(szSeg, pMsgAll, i);
|
|
|
+ szSeg[i] = 0;
|
|
|
+ if (pMsgAll[i] != 0)
|
|
|
+ pRtn = (char*)(pMsgAll + i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return pRtn;
|
|
|
+ }
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ INT SMS_INIT(IN CONST BYTE& byCommPort, IN CONST DWORD& dwBaudRate, IN CONST BYTE& bySize, IN CONST BYTE& byParity, IN CONST BYTE& byStopBits, IN CONST BYTE& byStartAddr, IN CONST INT& nInterval, IN CONST INT& nMaxSMSChar)
|
|
|
+ {
|
|
|
+ _nMaxSMSChar = nMaxSMSChar;
|
|
|
+ if (_pSMSComm == NULL)
|
|
|
+ {
|
|
|
+ _pSMSComm = new CCommRS232;
|
|
|
+ if (!_pSMSComm->InitComm(byCommPort, dwBaudRate, bySize, byParity, byStopBits, byStartAddr, nInterval))
|
|
|
+ {
|
|
|
+ delete _pSMSComm;
|
|
|
+ _pSMSComm = NULL;
|
|
|
+ return ERR_CODE_SMS_OPEN_COMM;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置成PDU模式;
|
|
|
+ TCHAR szBuf[MAX_SIZE] = _T("AT+CMGF=0\r");
|
|
|
+ INT nReturnSize = _pSMSComm->Write((BYTE*)szBuf, (INT)_tcslen(szBuf));
|
|
|
+
|
|
|
+ memset(szBuf, 0, MAX_SIZE);
|
|
|
+ nReturnSize = _pSMSComm->Read((BYTE*)szBuf, MAX_SIZE - 1);
|
|
|
+ if (nReturnSize)
|
|
|
+ {
|
|
|
+ if (_tcsstr(szBuf, _T("OK")) == NULL)
|
|
|
+ {
|
|
|
+ delete _pSMSComm;
|
|
|
+ _pSMSComm = NULL;
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ delete _pSMSComm;
|
|
|
+ _pSMSComm = NULL;
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+#if 0
|
|
|
+ // 把卡里的第一条短信删掉;
|
|
|
+ _tcscpy_s(szBuf, _T("AT+CMGD=1\r"));
|
|
|
+ nReturnSize = _pSMSComm->Write((BYTE*)szBuf, (INT)_tcslen(szBuf));
|
|
|
+
|
|
|
+ memset(szBuf, 0, MAX_SIZE);
|
|
|
+ nReturnSize = _pSMSComm->Read((BYTE*)szBuf, MAX_SIZE - 1);
|
|
|
+#endif
|
|
|
+ InitializeCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ VOID SMS_UNINIT()
|
|
|
+ {
|
|
|
+ // 结束线程;
|
|
|
+ if (_hCtrlEvent)
|
|
|
+ SetEvent(_hCtrlEvent);
|
|
|
+
|
|
|
+ if (_hSMSReceiveThread)
|
|
|
+ {
|
|
|
+ WaitForSingleObject(_hSMSReceiveThread, INFINITE);
|
|
|
+ CloseHandle(_hSMSReceiveThread);
|
|
|
+ _hSMSReceiveThread = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_hCtrlEvent)
|
|
|
+ CloseHandle(_hCtrlEvent);
|
|
|
+ _hCtrlEvent = NULL;
|
|
|
+
|
|
|
+ DeleteCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ // 清理串口句柄;
|
|
|
+ if (_pSMSComm)
|
|
|
+ {
|
|
|
+ delete _pSMSComm;
|
|
|
+ _pSMSComm = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ INT SMS_SENDMSG(IN CONST TCHAR *pTel, IN CONST TCHAR *pContent, IN TCHAR *pErrorMsg)
|
|
|
+ {
|
|
|
+ if (pContent == NULL || pTel == NULL)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ INT nRet = 0;
|
|
|
+ BOOL bRet = FALSE;
|
|
|
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
+
|
|
|
+ CString strMsg = pContent;
|
|
|
+ if (MyCharCount(strMsg) < 70)
|
|
|
+ {
|
|
|
+ nRet = SendSMS(pTel, strMsg, pErrorMsg);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ char* szMsg2 = new char[strlen(strMsg) + 1];
|
|
|
+ strcpy(szMsg2, strMsg);
|
|
|
+ char* pMsgSegLeft = (char*)szMsg2;
|
|
|
+ bRet = TRUE;
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+ char szMsgSegSend[255] = { 0 };
|
|
|
+ int nMaxCharCanSend = _nMaxSMSChar; // 最大能够发送的字符,暂固定为70
|
|
|
+ pMsgSegLeft = PickSegTxt(pMsgSegLeft, szMsgSegSend, nMaxCharCanSend);
|
|
|
+ nRet = SendSMS(pTel, szMsgSegSend, pErrorMsg);
|
|
|
+ if (!nRet)
|
|
|
+ {
|
|
|
+ bRet = FALSE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (pMsgSegLeft == NULL)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ delete[]szMsg2;
|
|
|
+ }
|
|
|
+ if (bRet && g_nMakeCall == 1)
|
|
|
+ {
|
|
|
+ //拨号通知用户留心短信(拨号20秒)
|
|
|
+ char WriteBuff[MAX_WRITE_STR_LEN + 1] = { 0 };
|
|
|
+ char ReadBuff[MAX_READ_STR_LEN + 1] = { 0 };
|
|
|
+ sprintf(WriteBuff, "ATD%s;\r", pTel);
|
|
|
+ int iOffset = (int)strlen(WriteBuff);
|
|
|
+
|
|
|
+ _pSMSComm->Write((BYTE *)WriteBuff, iOffset);
|
|
|
+ int nLen = _pSMSComm->Read((BYTE *)ReadBuff, MAX_READ_STR_LEN);
|
|
|
+ COleDateTime timeStart = COleDateTime::GetCurrentTime();
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+#ifndef _DEBUG
|
|
|
+ //CString strToStop;
|
|
|
+ //if(GetTempVar("ToStop", strToStop) && strToStop == "1")
|
|
|
+ // break;
|
|
|
+#endif
|
|
|
+ COleDateTimeSpan span = COleDateTime::GetCurrentTime() - timeStart;
|
|
|
+ if (span.GetTotalSeconds() > 20)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ sprintf(WriteBuff, "ATH\r");
|
|
|
+ iOffset = (int)strlen(WriteBuff);
|
|
|
+ _pSMSComm->Write((BYTE *)WriteBuff, iOffset);
|
|
|
+ nLen = _pSMSComm->Read((BYTE *)ReadBuff, MAX_READ_STR_LEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ return nRet;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:SMS_GETCSQ[12/21/2017 Home];
|
|
|
+ /* 描述:获取短信猫信息强度(AT+CSQ指令);
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:CSQ<0-10>,n 表示信号不足 CSQ<11-31>,n 表示信号充足 CSQ<大于99>,n 表示信号不足;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL SMS_GETCSQ(int iMin, int iMax, int &iNowData)
|
|
|
+ {
|
|
|
+ bool bRet = false;
|
|
|
+
|
|
|
+ EnterCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ char szBuf[MAX_SIZE] = { 0 };
|
|
|
+ //取号码
|
|
|
+ strcpy(szBuf, "AT+CSQ\r");
|
|
|
+ int nLen = _pSMSComm->Write((BYTE *)szBuf, (int)strlen(szBuf));
|
|
|
+ memset(szBuf, 0, sizeof(szBuf));
|
|
|
+ nLen = _pSMSComm->Read((BYTE *)szBuf, MAX_SIZE - 1);
|
|
|
+
|
|
|
+ CString str;
|
|
|
+ str.Format("%s", szBuf);
|
|
|
+ int nPos = str.Find("CSQ: ");
|
|
|
+ str = str.Mid(nPos + 5, 2);
|
|
|
+
|
|
|
+ iNowData = atoi(str);
|
|
|
+ if (iNowData >= iMin && iNowData <= iMax)
|
|
|
+ bRet = true;
|
|
|
+
|
|
|
+ LeaveCriticalSection(&_csRS232);
|
|
|
+
|
|
|
+ return bRet;
|
|
|
+ }
|
|
|
+
|
|
|
+ INT SMS_SetCallBack(PFCALLBACK Func)
|
|
|
+ {
|
|
|
+ if (Func == NULL || gEnalbeAlarmCallBack != NULL)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ gEnalbeAlarmCallBack = Func;
|
|
|
+
|
|
|
+ _hCtrlEvent = ::CreateEvent(NULL, TRUE, 0, 0);
|
|
|
+
|
|
|
+ DWORD dwReceiveSmsThreadId;
|
|
|
+ _hSMSReceiveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SMSReceiveThread, NULL, 0, &dwReceiveSmsThreadId);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+};
|