18,356
社区成员
发帖
与我相关
我的任务
分享
//参考资料
一、短信中心号码处理:用字符串 addr 表示
1、将短信息中心号码去掉+号,看看长度是否为偶数,如果不是,最后添加F
即 addr = "+8613800200500"
=> addr = "8613800200500F"
2、将奇数位和偶数位交换。
=> addr = "683108200005F0"
3、将短信息中心号码前面加上字符91,91是国际化的意思
=> addr = "91683108200005F0"
4、算出 addr 长度,结果除2,格式化成2位的16进制字符串,16 / 2 = 8 => "08"
=> addr = "0891683108200005F0"
二、手机号码处理:用字符串 phone
1、将手机号码去掉+号,看看长度是否为偶数,如果不是,最后添加F
即 phone = "+8613602433649"
=> phone = "8613602433649F"
2、将手机号码奇数位和偶数位交换。
=> phone = "683106423346F9"
三、短信息部分处理:用字符串 msg 表示
1、转字符串转换为Unicode代码,例如“工作愉快!”的unicode代码为 5DE54F5C61095FEBFF01,
(转换函数见最后附录)
2、将 msg 长度除2,保留两位16进制数,即 5DE54F5C61095FEBFF01 = 20 / 2 => "0A",再加上 msg
=> msg = "0A5DE54F5C61095FEBFF01"
四、组合
1、手机号码前加上字符串 11000D91(1100:固定,0D:手机号码的长度,不算+号,十六进制表示,91:发送到手机为91,发送到小灵通为81),
即 phone = "11000D91" + phone
=> 11000D91683106423346F9
2、手机号码后加上 000800 和刚才的短信息内容,000800也写死就可以了
即 phone = phone + "000800" + msg
即 11000D91683106423346F9 + 000800 + 0A5DE54F5C61095FEBFF01
=> phone = 11000D91683106423346F90008000A5DE54F5C61095FEBFF01
3、phone 长度除以2,格式化成2位的十进制数
//我用c++的实现
/* 短信预处理 */
class SplitMessage
{
public:
SplitMessage()
{
}
~SplitMessage()
{
}
SplitMessage(MessageStruct OneMessage)
{
m_Message = OneMessage;
SplitInit();
}
//用新的短信拼接
void SetMessage(MessageStruct OneMessage)
{
m_Message = OneMessage;
SplitInit();
}
public:
void doWork()
{
/* 1 */
SplitAddrStr(m_LpAddr,m_TempArr,m_iA,m_iA,m_Message.Addr);
/* 2 */
SplitPhoneStr(m_LpPhone,m_TempArr,m_iP,m_iP,m_Message.Phone);
/* 3 */
SplitMessageStr(m_LpMsg,m_TempArr,m_iM,m_iM,m_Message.Message);
/* 4 */
SplitAllPduStr(m_LpAddr,m_LpPhone,m_LpMsg,m_iA,m_iP,m_iM);
strcat(m_PduResult, "\x01a"); // 以Ctrl-Z结束
m_iPduLeng = m_iA + m_iP + m_iM+2;
}
//得到pdu串
const char * const getPduStr()
{
return m_PduResult;
}
int getpduLength()
{
return m_iPduLeng;
}
int getIntCMGS()
{
return m_AT_CMGS;
}
private:
const char * getAddr()
{
return m_LpAddr;
}
const char * getPhone()
{
return m_LpPhone;
}
const char * getMsg()
{
return m_LpMsg;
}
private:
//对象初始化
void SplitInit()
{
/* 赋值长度 */
m_iA = m_Message.iAddr;
m_iP = m_Message.iPhone;
m_iM = m_Message.iMessage;
assert(m_iA < MESSAGE_NUMBER_SIZE);
assert(m_iP < MESSAGE_NUMBER_SIZE);
assert(m_iM < MESSAGE_TEXT_SIZE);
/* 拷贝内存 */
memcpy(m_LpAddr,m_Message.Addr,m_Message.iAddr);
memcpy(m_LpPhone,m_Message.Phone,m_Message.iPhone);
memcpy(m_LpMsg,m_Message.Message,m_Message.iMessage);
memset(m_PduResult,'\0',MESSAGE_PDU_SIZE);
memset(m_TempArr,'\0',MESSAGE_PDU_SIZE);
/* 赋结束符 */
*(m_LpAddr + m_iA+1) ='\0';
*(m_LpPhone + m_iP+1)='\0';
*(m_LpMsg + m_iM+1)='\0';
}
private:
/* 第一部分 拼接 短信服务中心号码*/
//LpResultAddr 处理后得到的串
//LpAddr 短信服务中心号码 例8615800255000(需要使用at指令得到)
//iAlen 短信服务中心号码的长度
void SplitAddrStr(char * LpResultAddr,char * LpAddr,int iAlen,int & iUseLen,const char * Addr)
{
assert(NULL != LpAddr && NULL != LpResultAddr);
memcpy(LpAddr,Addr,iAlen+1);
assert(strlen(LpAddr) == 13);
if (strlen(LpAddr)%2 == 1)//1.不够偶数位加'F'
{
*(LpAddr+iAlen) = 'F';
*(LpAddr+iAlen+1) ='\0';
iAlen ++;
}
ReBackChar(LpAddr,iAlen);//2奇偶位调换
strcpy(LpResultAddr,LpAddr);
SwapMemoryArr(LpResultAddr,"91",LpAddr,MESSAGE_NUMBER_SIZE,2,iAlen);//3前面加"91"
iAlen += 2;
memcpy(LpAddr,LpResultAddr,iAlen);
int iResult= iAlen/2;
char tmp[32];
itoa(iResult,tmp,16);
if (strlen(tmp)<2)
{
char tt=tmp[0];
tmp[0]='0';
tmp[1]=tt;
tmp[2]='\0';
}
SwapMemoryArr(LpResultAddr,tmp,LpAddr,MESSAGE_NUMBER_SIZE,strlen(tmp),iAlen);//添加PDU串中的SMSC信息长度
iAlen +=2;
*(LpResultAddr + iAlen +1) ='\0';
iUseLen = iAlen;
}
/* 第二部分 拼接 目标地址号码 */
//LpResultPhone处理后的串
//LpPhone 目标电话号
//iPhoneLen电话号长度
//UseLen 处理后串长度
void SplitPhoneStr(char * LpReslutPhone,char * LpPhone,int iPhoneLen,int & iUseLen,const char * Phone)
{
assert(NULL != LpPhone && NULL != LpReslutPhone);
memcpy(LpPhone,Phone,iPhoneLen+1);
assert(strlen(LpPhone) == 13);
if (strlen(LpPhone)%2 == 1)//1.不够偶数位加'F'
{
*(LpPhone+iPhoneLen) = 'F';
*(LpPhone+iPhoneLen+1) = '\0';
iPhoneLen++;
}
ReBackChar(LpPhone,iPhoneLen);//2奇偶位调换
SwapMemoryArr(LpReslutPhone,"11000D91",LpPhone,MESSAGE_NUMBER_SIZE,8,iPhoneLen);//91为手机,此处写死只能发给手机
iPhoneLen += 8;
*(LpReslutPhone+iPhoneLen) = '\0';
memcpy(LpPhone,LpReslutPhone,iPhoneLen);
SwapMemoryArr(LpReslutPhone,LpPhone,"000800",MESSAGE_NUMBER_SIZE,iPhoneLen,6);
iPhoneLen +=6;
*(LpReslutPhone+iPhoneLen) = '\0';
iUseLen = iPhoneLen;
}
/* 第三部分 拼接 短信内容 */
//LpResultMessage 处理后的短信串
//LpMessage 原短信串
//iMessageLen
//UseLen处理后的长度
void SplitMessageStr(char * LpResultMessage,char * LpMessage,int iMessageLen,int & iUseLen,const char * Message)
{
memcpy(LpMessage,Message,iMessageLen+1);
//转为unicode码
unsigned char buf[256];
int iLength= gsmEncodeUcs2(LpMessage,buf,iMessageLen);
iMessageLen = gsmBytesString(buf,LpResultMessage,iLength);
*(LpResultMessage+iMessageLen+1) = '\0';
char CDivisor[32];
itoa(iMessageLen/2,CDivisor,16);
if (strlen(CDivisor) < 2)
{
char C = CDivisor[0];
CDivisor[0]='0';
CDivisor[1]=C;
CDivisor[2]='\0';
SwapMemoryArr(LpMessage,CDivisor,LpResultMessage,MESSAGE_PDU_SIZE,2,iMessageLen);//前两位短信长度
iMessageLen += 2;
memcpy(LpResultMessage,LpMessage,iMessageLen);
*(LpResultMessage+ iMessageLen +1) ='\0';
}
else
{
char temp[32];
memset(temp,'\0',32);
memcpy(temp,CDivisor,2);
SwapMemoryArr(LpMessage,temp,LpResultMessage,MESSAGE_PDU_SIZE,2,iMessageLen);//前两位短信长度
iMessageLen += 2;
memcpy(LpResultMessage,LpMessage,iMessageLen);
*(LpResultMessage+ iMessageLen +1) ='\0';
}
iUseLen =iMessageLen;
}
/* 第四部分 拼接 整个Pdu串 */
//
//
void SplitAllPduStr(char * LpAddr,char * LpPhone,char * LpMessage,int iA,int iP,int iM)
{
SwapMemoryArr(m_TempArr,LpPhone,LpMessage,MESSAGE_PDU_SIZE,iP,iM);//phone + msg
*(m_TempArr+ iP +iM) ='\0';
int iNo = strlen(m_TempArr)/2;
m_AT_CMGS = iNo;//地址和短信内容的长度
SwapMemoryArr(m_PduResult,LpAddr,m_TempArr,MESSAGE_PDU_SIZE,iA,(iP+iM));//addr + 上面的结果
*(m_PduResult + iA+iP +iM) ='\0';
}
private://辅助函数
//前后拼接两个串成为新串
void SwapMemoryArr(char * LpResult,const char * LpFront,const char * LpTarget,int iRLen,int iFLen,int iTLen)
{
assert(LpResult!=NULL && LpFront !=NULL && LpTarget!=NULL);
assert((iFLen+iTLen) < iRLen);
memcpy(LpResult,LpFront,iFLen);
memcpy((LpResult+iFLen),LpTarget,iTLen);
}
//奇偶交换
void ReBackChar(char * LpR,int iLen)
{
int iIndex=0;
for(int i=1;i<(iLen+1);i++)
{
iIndex = i-1;//数组索引下标
int x =i%2;
if (x == 1)//如果是奇数则交换
{
char lt = *(LpR+iIndex);
*(LpR+iIndex) = *(LpR+iIndex+1);
*(LpR+iIndex+1) = lt;
}
}
}
// UCS2编码
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: pDst - 目标编码串指针
// 返回: 目标编码串长度
int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)
{
int nDstLength; // UNICODE宽字符数目
WCHAR wchar[128]; // UNICODE串缓冲区
// 字符串-->UNICODE串
nDstLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);
// 高低字节对调,输出
for(int i=0; i<nDstLength; i++)
{
*pDst++ = wchar[i] >> 8; // 先输出高位字节
*pDst++ = wchar[i] & 0xff; // 后输出低位字节
}
// 返回目标编码串长度
return nDstLength * 2;
}
// 字节数据转换为可打印字符串
// 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"
// 输入: pSrc - 源数据指针
// nSrcLength - 源数据长度
// 输出: pDst - 目标字符串指针
// 返回: 目标字符串长度
int gsmBytesString(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
const char tab[]="0123456789ABCDEF"; // 0x0-0xf的字符查找表
for (int i = 0; i < nSrcLength; i++)
{
*pDst++ = tab[*pSrc >> 4]; // 输出高4位
*pDst++ = tab[*pSrc & 0x0f]; // 输出低4位
pSrc++;
}
// 输出字符串加个结束符
*pDst = '\0';
// 返回目标字符串长度
return (nSrcLength * 2);
}
// UCS2解码
// 输入: pSrc - 源编码串指针
// nSrcLength - 源编码串长度
// 输出: pDst - 目标字符串指针
// 返回: 目标字符串长度
int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
int nDstLength; // UNICODE宽字符数目
WCHAR wchar[128]; // UNICODE串缓冲区
// 高低字节对调,拼成UNICODE
for(int i=0; i<nSrcLength/2; i++)
{
wchar[i] = *pSrc++ << 8; // 先高位字节
wchar[i] |= *pSrc++; // 后低位字节
}
// UNICODE串-->字符串
nDstLength = WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);
// 输出字符串加个结束符
pDst[nDstLength] = '\0';
// 返回目标字符串长度
return nDstLength;
}
private :
MessageStruct m_Message;
char m_PduResult[MESSAGE_PDU_SIZE];//PDU串
int m_iPduLeng;
char m_TempArr[MESSAGE_PDU_SIZE];//中间变量缓冲区
private:
char m_LpAddr[MESSAGE_NUMBER_SIZE]; //缓冲,短信服务中心号码
char m_LpPhone[MESSAGE_NUMBER_SIZE]; //缓冲,目标手机号
char m_LpMsg[MESSAGE_PDU_SIZE];//缓冲,信息内容
int m_AT_CMGS;//AT指令参数
int m_iA;//短信中心号码长度
int m_iP;//手机号长度
int m_iM;//信息长度
};
#define MESSAGE_PDU_SIZE 800 //编码后pdu串的最大长度
#define MESSAGE_NUMBER_SIZE 32 //号码的最大长度
#define MESSAGE_TEXT_SIZE 100 //短信最大长度
/* 短信基本内容 */
typedef struct {
char Addr[32]; //服务中心号码,服务中心号码是短消息的必有属性,系统通过at指令获得并赋值
//编辑短信时看不到,新的手机卡一般买到手都是设置好的,
char Phone[32];//对方号码
char Message[200];//短信内容
int iAddr;//串长
int iPhone;//串长
int iMessage;//串长
} MessageStruct;
//开了一个线程处理发短信的,合理么,运行一段时间后系统非常慢
//短信工作线程
void SmsWorkThread(void * t)
{
//串口操作类,全局
wchar_t * strCom = L"COM1";
BOOL bIsOpen = UseComm.OpenComm(strCom,9600,NOPARITY,8,ONESTOPBIT);
if (!bIsOpen)
{
printf("串口打开失败!短信报警启动失败!\n");
return;
}
while (true)
{
//PushMessage();//加一条短信
if (m_MessageDeque.size()!=0)//队列中是否还有短信
{
MessageStruct MyMessage = m_MessageDeque.front();
m_MessageDeque.pop_front();
SplitMessage * MessWork = new SplitMessage(MyMessage);
//MessWork->SetMessage();
MessWork->doWork();
char cmd[16];
char ans[50];
memset(ans,'\0',50);
UseComm.WriteComm("at\r",3);
int nnLength =UseComm.ReadComm(ans,128);
// 命令中的长度,不包括SMSC信息长度,以数据字节计
sprintf(cmd, "AT+CMGS=%d\r", MessWork->getIntCMGS()); // 生成命令
UseComm.WriteComm("AT+CMGF=0\r",strlen("AT+CMGF=0\r"));
int nLength =UseComm.ReadComm(ans,128);
UseComm.WriteComm(cmd, strlen(cmd)); // 先输出命令串
nLength =UseComm.ReadComm(ans,50);
// 根据能否找到"\r\n> "决定成功与否
if(strstr(ans, "> ") != NULL && strstr(ans,"ERROR") == NULL)
{
char SendContent[200];
memcpy(SendContent,MessWork->getPduStr(),MessWork->getpduLength());
UseComm.WriteComm(SendContent,strlen(SendContent));
Sleep(3000);
nLength = UseComm.ReadComm(ans,128);
if (strstr(ans,"OK") != NULL && strstr(ans,"ERROR") ==NULL)
{
printf("发送成功一条短信!\n");
}
UseComm.WriteComm("ATE\r",4);
nLength = UseComm.ReadComm(ans,50);
UseComm.WriteComm("\x01a\r",2);
nLength = UseComm.ReadComm(ans,50);
UseComm.WriteComm("AT\r",3);
nLength = UseComm.ReadComm(ans,50);
}
else
{
UseComm.WriteComm("\x01a",2);
UseComm.WriteComm("AT\r",3);
UseComm.WriteComm("ATE\r",4);
nLength = UseComm.ReadComm(ans,50);
}
}
}
BOOL bIsClose = UseComm.CloseComm();
if (!bIsClose)
{
printf("串口关闭失败\n");
}
return ;
}
// 服务中心号码 /* 加个空格式 */
unsigned char *pSrc; int *pN /* 这样更好 */
// VC编程网络就参考微软的MSDN就OK