📄 smsoper.cpp
字号:
{
const char* pchManufacturer;
DoAtCmd(hCom,"AT+CGMI");
//do with what the program received from serial device.
char chBack[200]={0};
int nLength=OnReadComm(hCom,chBack,sizeof(chBack));
if (nLength==0) return NULL;
//没有成功的响应
if (strstr(chBack, "OK") ==NULL) return NULL;
char m_chManufacturer[50];
memset(m_chManufacturer,'\0',sizeof(m_chManufacturer));
memcpy(m_chManufacturer,chBack+3,14);
pchManufacturer=m_chManufacturer;
return pchManufacturer;
}
// 如果手机号码字符串前面有"+"则去掉,如果前面没有86号码,则加上86
// 输入: 手机号码字符串
const char* CSmsOper::OnIs86(const char *p)
{
const char *pTel;
char chTmp[20]={0};
if (strncmp(p,"+",1)==0)
{
memcpy(chTmp,p+1,sizeof(chTmp));
pTel=chTmp;
}
else
{
pTel=p;
}
if (strncmp(pTel,"86",2)!=0)
{
char chTel[20]={0};
memcpy(chTel,"86",2);
memcpy(chTel+2,pTel,sizeof(chTel)-2);
pTel=chTel;
}
return pTel;
}
// 发送短消息
// 输入: pchMobile - 对方手机号码
// 输入: pchSms - 要发送短消息缓冲区
// 输入:const char*pchSCA,短信中心号码
// 输入: nType表示对方手机类型,比如小灵通还是移动、联通的手机
// 输入:nHcom为哪个串口的句柄
// 返回: -1失败,0为成功
int CSmsOper::OnSendMess(int nHcom,int nType,const char*pchSCA,const char*pchMobile, const char* pchSms)
{
SM_PARAM st_Param;
memset(&st_Param, 0, sizeof(SM_PARAM));
char chSCA[16]={0};
char chMobile[16]={0};
memcpy(chSCA,OnIs86(pchSCA),sizeof(chSCA));
//memcpy(chMobile,OnIs86(pchMobile),sizeof(chMobile));
// 填充短消息结构
memcpy(st_Param.SCA, chSCA,sizeof(st_Param.SCA));
memcpy(st_Param.TPA, pchMobile,sizeof(st_Param.TPA));
memcpy(st_Param.TP_UD, pchSms,sizeof(st_Param.TP_UD));
st_Param.TP_PID = 0;
st_Param.TP_DCS = GSM_UCS2;
return OnSendSms(nHcom,&st_Param,nType);
}
/*
// 接收短信函数
// 输入: hCom - 从那个com口句柄接收到的消息
// 输入: nLenOutBuffer-输出数据的长度
// 输出: bDel - 读到新消息后是否将其删除
// 输出:pchText-接收到短信内容,固定格式如下:
typedef struct {
char SCA[16]; // 短消息服务中心号码(SMSC地址)
char TPA[16]; // 目标号码或回复号码(TP-DA或TP-RA)
char TP_PID; // 用户信息协议标识(TP-PID)
char TP_DCS; // 用户信息编码方式(TP-DCS)
char TP_SCTS[16]; // 服务时间戳字符串(TP_SCTS), 接收时用到
char TP_UD[160]; // 原始用户信息(编码前或解码后的TP-UD)
short index; // 短消息序号,在读取时用到
} SM_PARAM
将结构体数据依次放入缓冲区中间(所以建议输出缓冲区尽量定义大一些)
// 返回: -1失败,大于0则成功,为短信条数
*/
int CSmsOper::OnRecvMess(int hCom,const unsigned int nLenOutBuffer,const char *pchOutBuffer,bool bDel)
{
SM_PARAM st_Param[200];
for (int i=0;i<200;i++)
{
memset(&st_Param[i],'\0',sizeof(SM_PARAM));
}
int iCount=OnRecvSms(hCom,st_Param);
if (iCount<1) return iCount;
for(i=0;i<iCount;i++)
{
//如果输出的字符串的长度比存储短信长度短,则只复制一定长度的数据
if (nLenOutBuffer<(i*sizeof(SM_PARAM)) ) break;
//将结构体数据放入到缓冲区中输出
memcpy((void *)(pchOutBuffer+i*sizeof(SM_PARAM)),&st_Param[i],sizeof(SM_PARAM));
//读写一条消息后,就从sim卡上删除掉该消息(要问清楚,也可以自己测试下)
if (bDel) OnDeleteAppointed(hCom,st_Param[i].index);
}
return iCount;
}
// 打开串口
// 返回: 如果大于0则为获取的com接口的句柄,小于0则为失败
int CSmsOper::OnOpenCom(char *pPort, int nBaudRate, int nParity, int nByteSize, int nStopBits)
{
DCB dcb; // 串口控制块
COMMTIMEOUTS timeouts = { // 串口超时控制参数
200, // 读字符间隔超时时间: 100 ms
1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
600, // 基本的(额外的)读超时时间: 500 ms
1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
200}; // 基本的(额外的)写超时时间: 100 ms
HANDLE hCom = CreateFile(pPort, // 串口名称或设备路径
GENERIC_READ | GENERIC_WRITE, // 读写方式
0, // 共享方式:独占
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
if(hCom == INVALID_HANDLE_VALUE)
{
return -1; // 打开串口失败
}
dcb.BaudRate = nBaudRate;
dcb.ByteSize = nByteSize;
dcb.Parity = nParity;
dcb.StopBits = nStopBits;
dcb.fBinary=TRUE;
dcb.fDsrSensitivity=false;
dcb.fParity=0;
dcb.fOutX=false;
dcb.fInX=false;
dcb.fNull=false;
dcb.fAbortOnError=TRUE;
dcb.fOutxCtsFlow=FALSE;
dcb.fOutxDsrFlow=false;
dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity=false;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fOutxCtsFlow=false;
dcb.fOutxCtsFlow=false;
// 设置输入输出缓冲区大小
if (0==SetupComm(hCom, 4096, 1024))
{
OnErrorMsg("设置串口通讯失败SetupComm失败");
return -2;
}
if (0==SetCommTimeouts(hCom, &timeouts))
{
OnErrorMsg("设置串口通讯SetCommTimeouts!失败");
return -3;
}// 设置超时
// 取DCB
if (0 == GetCommState(hCom, &dcb))
{
OnErrorMsg("获取串口通讯状态失败");
return -4;
}
char chBaud[40]={0};
sprintf(chBaud,"baud=%d parity=%c data=%d stop=%d",nBaudRate,'N',nByteSize,nStopBits);
if (0==BuildCommDCB(chBaud,&dcb))
{
OnErrorMsg("BuildCommDCB失败");
return -5;
}
if (0 == SetCommState(hCom, &dcb))
{
OnErrorMsg("设置串口时候失败SetCommState");
return -6;
}
InitializeCriticalSection(&m_ComOperCritical); //发送短信的锁
return int(hCom);
}
void CSmsOper::OnErrorMsg(char *pchInput)
{
TCHAR szBuf[300]={0};
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
_snprintf(szBuf,sizeof(szBuf)-1,"%s failed with error %d: %s", pchInput, dw, lpMsgBuf);
MessageBox(NULL, szBuf, "Error", MB_OK);
LocalFree(lpMsgBuf);
}
// 关闭串口
int CSmsOper::OnCloseComm(int hCom)
{
FlushFileBuffers((void *)hCom);
return CloseHandle((void *)hCom);
}
// 写串口
// 输入: pData - 待写的数据缓冲区指针
// nLength - 待写的数据长度
// 返回: 实际写入的数据长度
int CSmsOper::OnWriteComm(int hCom,void* pData, int nLength)
{
DWORD dwNumWrite; // 串口发出的数据长度
DWORD dwErrors=0;
try
{
EnterCriticalSection(&m_ComOperCritical);
ClearCommError((void *)hCom, &dwErrors, NULL);
PurgeComm((void *)hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
WriteFile((void *)hCom, pData, (DWORD)nLength, &dwNumWrite, NULL);
LeaveCriticalSection(&m_ComOperCritical);
}
catch(...)
{
LeaveCriticalSection(&m_ComOperCritical);
return -1;
}
return (int)dwNumWrite;
}
// 读串口
// 输入: pData - 待读的数据缓冲区指针
// nLength - 待读的最大数据长度
// 返回: 实际读出的数据长度
int CSmsOper::OnReadComm(int hCom,void* pData, int nLength)
{
DWORD dwNumRead; // 串口收到的数据长度
try
{
EnterCriticalSection(&m_ComOperCritical);
BOOL bRet=ReadFile((void *)hCom, pData, (DWORD)nLength, &dwNumRead, NULL);
if (!bRet)
{
PurgeComm((void *)hCom,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
ReadFile((void *)hCom, pData, (DWORD)nLength, &dwNumRead, NULL);
}
LeaveCriticalSection(&m_ComOperCritical);
}
catch(...)
{
LeaveCriticalSection(&m_ComOperCritical);
return -1;
}
// PurgeComm((void *)hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
return (int)dwNumRead;
}
//清空串口的缓冲区,如果失败了则结果为0,没有失败的话,结果为非0
int CSmsOper::OnClearCom(int nHCom)
{
return PurgeComm((void *)nHCom,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
}
int CSmsOper::OnReadCommOkErr(int hCom, char *pchBuf, int nLength)
{
DWORD dwNumRead; // 串口收到的数据长度
char chData[8000]={0};
int nRecvDataLen=0;
int nDataLen=0;
// 串口错误号
DWORD dwErrors = 0;
try
{
EnterCriticalSection(&m_ComOperCritical);
while( nRecvDataLen < nLength )
{
if( ReadFile( (void *)hCom, chData + nRecvDataLen, nLength - nRecvDataLen, &dwNumRead, NULL ) )
{
if( dwNumRead > 0 )
{
nRecvDataLen += dwNumRead;
}
else
{
LeaveCriticalSection(&m_ComOperCritical);
return -1;
}
}
else
{
ClearCommError((void *)hCom, &dwErrors, NULL);
PurgeComm((void *)hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
LeaveCriticalSection(&m_ComOperCritical);
return -1;
}
//判断是否接收到错误或者正确的信息
nDataLen=0;
nDataLen=OnRecWhole(chData,pchBuf,"OK\r\n");
if (nDataLen>0)
{
LeaveCriticalSection(&m_ComOperCritical);
return nDataLen;
}
//判断是否接收到错误或者正确的信息
nDataLen=OnRecWhole(chData,pchBuf,"ERROR\r\n");
if (nDataLen>0)
{
LeaveCriticalSection(&m_ComOperCritical);
return nDataLen;
}
}
LeaveCriticalSection(&m_ComOperCritical);
}
catch(...)
{
LeaveCriticalSection(&m_ComOperCritical);
return -1;
}
return nDataLen;
}
int CSmsOper::OnRecWhole(char *pchData,char *pchBuf, char *pchEnd)
{
//如果接收到数据当中包含了正确或者错误则停止接收数据
char *pdest;
int result=0,nDataLen=0;
pdest = strstr( pchData, pchEnd );
if (pdest!=NULL)
{
result = pdest - pchData + 1;
nDataLen=result+strlen(pchEnd);
try
{
memcpy(pchBuf,pchData,nDataLen);
}
catch(...)
{
return -1;
}
return nDataLen;
}
return 0;
}
int CSmsOper::OnReadBack(int hCom, char *pchBack,int nBack,char *pchOk, char *pchError,int nTimeOut)
{
long LastSaveBillTime=time(NULL);
//循环接受通讯终端的数据
while(1)
{
int iLen=OnReadComm(hCom,pchBack,nBack);
if (strstr(pchBack, pchOk)!=NULL)
{
return 1;
}
if (strstr(pchBack, pchError)!=NULL)
{
return -1;
break;
}
if(time(NULL) - LastSaveBillTime >= nTimeOut)
{
return -1;
break;
}
}
return 1;
}
//CMS ERROR: 304
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -