📄 sms.cpp
字号:
// 返回目标字符串长度
return nDstLength;
}
// 两两颠倒的字符串转换为正常顺序的字符串
// 如:"0891683139831012F7" --> "8613933801217"
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: pDst - 目标字符串指针
// 返回: 目标字符串长度
int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength)
{
int nDstLength; // 目标字符串长度
char ch; // 用于保存一个字符
// 复制串长度
nDstLength = nSrcLength;
// 两两颠倒
for(int i=0; i<nSrcLength;i+=2)
{
ch = *pSrc++; // 保存先出现的字符
*pDst++ = *pSrc++; // 复制后出现的字符
*pDst++ = ch; // 复制先出现的字符
}
// 最后的字符是'F'吗
if(*(pDst-1) == 'F')
{
pDst--;
nDstLength--; // 目标字符串长度减1
}
// 输出字符串加个结束符
*pDst = '\0';
// 返回目标字符串长度
return nDstLength;
}
// PDU编码,用于编制、发送短消息
// 输入: pSrc - 源PDU参数指针
// 输出: pDst - 目标PDU串指针
// 返回: 目标PDU串长度
int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst)
{
int nLength; // 内部用的串长度
int nDstLength; // 目标PDU串长度
unsigned char buf[512]; // 内部用的缓冲区
memset(buf,0,sizeof(buf));
// SMSC地址信息段
// 格式(13800311500)
nLength = strlen(pSrc->SCA); // SMSC地址字符串的长度
if(nLength!=0)
{
buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 2; // SMSC地址信息长度
buf[1] = 0x91; // 固定: 用国际格式号码
buf[2] = 0x68;
nDstLength = gsmBytes2String(buf, pDst, 3); // 转换3个字节到目标PDU串
nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength); // 转换SMSC号码到目标PDU串
}
else
{
buf[0] = 0;
nDstLength = gsmBytes2String(buf, pDst, 1); // 转换1个字节到目标PDU串
}
// TPDU段基本参数、目标地址等
nLength = strlen(pSrc->TPA); // TP-DA地址字符串的长度
buf[0] = 0x31; // 发送短信标识类型
buf[1] = 0; // TP-MR=0
buf[2] = (char)nLength; // 目标地址数字个数(TP-DA地址字符串真实长度)
buf[3] = 0x81; // 固定: 用国际格式号码
nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4); // 转换4个字节到目标PDU串
nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 转换TP-DA到目标PDU串
// TPDU段协议标识、编码方式、用户信息等
nLength = strlen(pSrc->TP_UD); // 用户信息字符串的长度
buf[0] = pSrc->TP_PID; // 协议标识(TP-PID)
buf[1] = pSrc->TP_DCS; // 用户信息编码方式(TP-DCS)
buf[2] = 0xa7; // 有效期(TP-VP)为24小时
if(pSrc->TP_DCS == GSM_7BIT)
{
// 7-bit编码方式
buf[3] = nLength; // 编码前长度
nLength = gsmEncode7bit(pSrc->TP_UD, &buf[4], nLength+1) + 4; // 转换TP-DA到目标PDU串
}
else if(pSrc->TP_DCS == GSM_UCS2)
{
// UCS2编码方式
buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength); // 转换TP-DA到目标PDU串
nLength = buf[3] + 4; // nLength等于该段数据长度
}
else
{
// 8-bit编码方式
buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength); // 转换TP-DA到目标PDU串
nLength = buf[3] + 4; // nLength等于该段数据长度
}
nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength); // 转换该段数据到目标PDU串
// 返回目标字符串长度
return nDstLength;
}
// PDU解码,用于接收、阅读短消息
// 输入: pSrc - 源PDU串指针
// 输出: pDst - 目标PDU参数指针
// 返回: 用户信息串长度
int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst)
{
int nDstLength; // 目标PDU串长度
unsigned char tmp,temp_86; // 内部用的临时字节变量
unsigned char buf[512]; // 内部用的缓冲区
memset(buf,0,sizeof(buf));
// SMSC地址信息段
gsmString2Bytes(pSrc, &tmp, 2); // 取长度
tmp = (tmp-1) * 2; // SMSC号码串长度
// 0x0891683139831012F7
pSrc += 4; // 指针后移,忽略SCA地址长度及SCA地址类型
// 跳过SMSC号码中的"+86"部分(联通及小灵通情况未知)
// 0x86两个字节
tmp -= 2;
pSrc += 2;
// 获取短信中心号码
gsmSerializeNumbers(pSrc, pDst->SCA, tmp); // 转换SMSC号码到目标PDU串
pSrc += tmp; // 指针后移
// TPDU段基本参数
gsmString2Bytes(pSrc, &tmp, 2); // 取基本参数
pSrc += 2; // 指针后移
// 取短信来源号码
gsmString2Bytes(pSrc, &tmp, 2); // 取长度
if(tmp & 1) tmp += 1; // 调整奇偶性
pSrc += 2; // 指针后移,忽略处理长度字节
pSrc += 2; // 指针后移,忽略处理来源端口类型(0x91)
gsmString2Bytes(pSrc, &temp_86, 2); // 取TP-RA号码的头两个字节
if(temp_86==0x68)
{
tmp -= 2; // 原TP-RA号码长度减少两个字节
pSrc += 2; // 指针后移,忽略"+86"两个字节部分
}
gsmSerializeNumbers(pSrc, pDst->TPA, tmp); // 取TP-RA号码
pSrc += tmp; // 指针后移
// TPDU段协议标识、编码方式、用户信息等
gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2); // 取协议标识(TP-PID)
pSrc += 2; // 指针后移
gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2); // 取编码方式(TP-DCS)
pSrc += 2; // 指针后移
gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14); // 服务时间戳字符串(TP_SCTS)
pSrc += 14; // 指针后移
// 开始处理时间字符串
char szTime[32];
char szTmp1[3];
char szTmp2[3];
char szTmp3[3];
char szTmp4[3];
char szTmp5[3];
char szTmp6[3];
char szTmp7[3];
memset(szTime,0,sizeof(szTime));
memset(szTmp1,0,sizeof(szTmp1));
memset(szTmp2,0,sizeof(szTmp2));
memset(szTmp3,0,sizeof(szTmp3));
memset(szTmp4,0,sizeof(szTmp4));
memset(szTmp5,0,sizeof(szTmp5));
memset(szTmp6,0,sizeof(szTmp6));
memset(szTmp7,0,sizeof(szTmp7));
if(pDst->TP_SCTS[0]>'8')
sprintf(szTmp1,"19");
else
sprintf(szTmp1,"20");
memcpy(szTmp2,&pDst->TP_SCTS[0],2);
memcpy(szTmp3,&pDst->TP_SCTS[2],2);
memcpy(szTmp4,&pDst->TP_SCTS[4],2);
memcpy(szTmp5,&pDst->TP_SCTS[6],2);
memcpy(szTmp6,&pDst->TP_SCTS[8],2);
memcpy(szTmp7,&pDst->TP_SCTS[10],2);
sprintf(szTime,"%s%s-%s-%s %s:%s:%s",szTmp1,szTmp2,szTmp3,szTmp4,szTmp5,szTmp6,szTmp7);
// 写入短信接收时间
memset(pDst->TP_SCTS,0,sizeof(pDst->TP_SCTS));
sprintf(pDst->TP_SCTS,szTime);
// 时间字符串处理完成
gsmString2Bytes(pSrc, &tmp, 2); // 用户信息长度(TP-UDL)
pSrc += 2; // 指针后移
if(pDst->TP_DCS == GSM_7BIT)
{
// 7-bit解码
nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4); // 格式转换
gsmDecode7bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
nDstLength = tmp;
}
else if(pDst->TP_DCS == GSM_UCS2)
{
// UCS2解码
nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换
nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
}
else
{
// 8-bit解码
nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换
nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
}
// 返回目标字符串长度
return nDstLength;
}
int WINAPI EncodePdu(char* pPort,char* pContent,char* pSmsc,char* pPreSend,char* pPdu)
{
SM_PARAM pSrc;
char szCmd[32]; // 命令串
char szPdu[512]; // PDU串
int nPduLength; // PDU串长度
unsigned char nSmscLength; // SMSC串长度
// 初始化基础数据
memset(&pSrc,0,sizeof(pSrc));
sprintf(pSrc.SCA,pSmsc);
sprintf(pSrc.TPA,pPort);
sprintf(pSrc.TP_UD,pContent);
pSrc.TP_DCS = GSM_UCS2;
pSrc.TP_PID = 0;
memset(szCmd,0,sizeof(szCmd));
memset(szPdu,0,sizeof(szPdu));
// 调用gsmEncodePdu进行编码
nPduLength = gsmEncodePdu(&pSrc, szPdu); // 根据PDU参数,编码PDU串
strcat(szPdu, "\x1a"); // 以Ctrl-Z结束
gsmString2Bytes(szPdu, &nSmscLength, 2); // 取PDU串中的SMSC信息长度
nSmscLength++; // 加上长度字节本身的长度
// 发送短信的指令中的长度,不包括SMSC信息长度,以数据字节计
sprintf(szCmd, "AT+CMGS=%d\r", nPduLength / 2 - nSmscLength); // 生成短信发送长度指令
// 填写返回数据内容
sprintf(pPreSend,szCmd);
sprintf(pPdu,szPdu);
return 0;
}
int WINAPI DecodePdu(char* pPort,char* pContent,char* pTime,char* pPdu)
{
SM_PARAM pMsg;
// 初始化基础数据
memset(&pMsg,0,sizeof(pMsg));
// 调用gsmDecodePdu进行解码
gsmDecodePdu(pPdu, &pMsg); // 进行PDU串解码
// 填写返回数据内容
sprintf(pPort,pMsg.TPA);
sprintf(pContent,pMsg.TP_UD);
sprintf(pTime,pMsg.TP_SCTS);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -