2 Star 2 Fork 4

zqw/WefeelSMS

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
SMS.pas 23.52 KB
一键复制 编辑 原始数据 按行查看 历史
zqw 提交于 2014-08-17 18:15 +08:00 . 提交全部文件
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
unit SMS;
interface
uses
Classes,Contnrs,AdPort,SysUtils,StrUtils,DateUtils;
type RECVSTATE=(RECVIDLE,CMT);
type SENDSTATE=(SENDIDLE,AT,ATE0,ATCNMI,ATCMGF,ATCSCA,ATCMGD,ATCSAS,ATW,ATCMGF2,ATCMGS,ATCMGF3,AT2);
type SENDMODE=(TEXTMODE=1,PDUMODE=0);
const DEFAULTMODE=PDUMODE;
type
TLine=record
Content:string; //一行内容
end;
type
TMessage=record //发送队列和接收队列都用此结构。
ID:integer; //唯一ID,由写发送队列的程序提供。接收队列不用。
Times:integer; //已尝试发送的次数
Code:string; //短信号码
Time:string; //短信时间。发送队列暂不用。
Content:string; //短信内容
end;
type
TResult=record //发送结果队列的结构
ID:integer; //唯一ID,取自发送队列
State:integer; //0发送成功,否则为发送失败的次数
end;
type
TShortMessage = class(TThread)
private
RecvQueue:TQueue; //行接收队列
SendMessageQueue:TQueue; //短信发送队列
RecvMessageQueue:TQueue; //短信接收队列 \
ResultQueue:TQueue; //发送结果队列
RecvString:string; //接收到的字符串
port:TApdComPort;
SendID,SendTimes:integer; //当前待发短信的ID和发送次数
SendCode,SendContent:string; //当前待发短信号码和内容
RecvCode,RecvTime,RecvContent:string; //当前正收的短信号码和内容
ErrorTimes:integer;//在某个状态下命令错误的次数
OverTime:TDateTime;
InReceivingLine:boolean;//true表示正在接收字符,还没收到换行,此时应避免发送字符。
NowMode:SENDMODE;
//CenterCode:string;
IsPDU:boolean;
FSendState:SENDSTATE;
FRecvState:RECVSTATE;
FSendSpeed:integer;
InOverLength:boolean; //是否正在发送超长短信
OverTotal:integer; //超长短信被分割的包总数
OverNo:integer; //当前短信是超长短信的第n条
OverIdentify:integer; //当前超长短信的唯一标识
procedure SetSendState(nowstate:SendState);
property SendState:SendState read FSendState write SetSendState;
procedure SetRecvState(nowstate:RECVSTATE);
property RecvState:RecvState read FRecvState write SetRecvState;
function SplitString(const Source,ch:string):TStringList;
procedure AddToRecvSpool(LineStr:string);
procedure DealReceivedLine(strReceivedLine:string);
procedure AddSMSToRecvSpool(Code,Time,Content:string);
function GetSMSFromSendSpool(pCode,pContent:pChar;out Id,Times:integer):boolean;
procedure AddSMSToSendSpool(Code,Content:PChar;Id,Times:integer);overload; //发短信
function GetComNumber():integer;
procedure SetComNumber(Number:integer);
function GetBaud():integer;
procedure SetBaud(Baud:integer);
procedure SendStr(data:string); //向串口发送字符串
procedure SendMessage(Code,Content:string); //发送短信
procedure DecodePDU(ReceivedLine:string);
function GetCountInSendMessageQueue():integer;
procedure DoWhenSendFail();
procedure AddToResultSpool(ID,State:integer);
//根据经验判断str是否全部由PDU格式字符串组成
function IsPDUFormat(str:string):boolean;
protected
procedure Execute; override;
public
procedure Open; //打开串口,开始线程
procedure Close; //关闭线程,关闭串口
procedure AddSMSToSendSpool(Code,Content:PChar;Id:integer);overload; //发短信
function GetSMSFromRecvSpool(pCode,pTime,pContent:pChar):boolean; //收短信
function GetFromRecvSpool(pContent:pChar):boolean; //直接收Modem返回的行
property ComNumber:integer read GetComNumber write SetComNumber;
property Baud:integer read GetBaud write SetBaud;
constructor Create();
destructor Destroy; override;
property WaitingSendCount:integer read GetCountInSendMessageQueue;
property SendSpeed:integer read FSendSpeed write FSendSpeed; //以秒计,每隔SendSpeed秒发送一次。
function GetFromResultSpool(out ID,State:integer):boolean; //获取发送结果
end;
implementation
uses PDU;
{ TShortMessage }
constructor TShortMessage.Create();
begin
port:=TApdComPort.Create(nil);
port.Parity:=pNone;
port.DataBits := 8;
port.StopBits := 1;
port.AutoOpen:=False;
port.ComNumber:=1;
port.Baud:=9600;
RecvQueue:=TQueue.Create();
SendMessageQueue:=TQueue.Create();
RecvMessageQueue:=TQueue.Create();
ResultQueue:=TQueue.Create();
FSendState:=SENDIDLE;
FRecvState:=RECVIDLE;
ErrorTimes:=0;
InReceivingLine:=false;
InOverLength:=false;
NowMode:=DEFAULTMODE;
//CenterCode:='8613800791500';
SendSpeed:=7;//默认间隔5秒发一次短信
inherited Create(true);
end;
destructor TShortMessage.Destroy;
begin
ResultQueue.Free;
RecvMessageQueue.Free;
SendMessageQueue.Free;
RecvQueue.Free;
port.Free;
inherited Destroy;
end;
procedure TShortMessage.Open;
begin
if port.Open=false then
begin
try
port.Open:=true;
NowMode:=PDUMODE;
FRecvState:=RECVIDLE;
SendState:=AT;
ErrorTimes:=0;
InReceivingLine:=false;
InOverLength:=false;
//CenterCode:='8613800791500';
self.Resume;
except
raise;// Exception.Create('无法打开串口'+IntToStr(port.ComNumber));
end;
end;
end;
procedure TShortMessage.Close;
begin
if port.Open=true then
begin
self.Terminate;
port.Open:=false;
end;
end;
function TShortMessage.GetComNumber():integer;
begin
Result:=port.ComNumber;
end;
procedure TShortMessage.SetComNumber(Number:integer);
begin
port.ComNumber:=Number;
end;
function TShortMessage.GetBaud():integer;
begin
Result:=port.Baud;
end;
procedure TShortMessage.SetBaud(Baud:integer);
begin
port.Baud:=Baud;
end;
procedure TShortMessage.SetSendState(nowstate:SENDSTATE);
begin
case nowstate of
AT:
SendStr('AT'+#13);
ATE0:
SendStr('ATE0'+#13); //关回显
ATCMGF:
SendStr('AT+CMGF='+IntToStr(integer(NowMode))+#13); //默认PDU模式
ATCNMI:
SendStr('AT+CNMI=2,2,0,0,0'+#13); //直接收短信
ATCSCA:
SendStr('AT+CSCA?'+#13); //读短信中心号码
ATCMGD:
SendStr('AT+CMGD=1,4'+#13); //删除所有短信
ATCSAS:
SendStr('AT+CSAS'+#13); //保存直接收短信的设置
ATW:
SendStr('AT&W'+#13); //保存
SENDIDLE:
;
ATCMGF2:
SendStr('AT+CMGF='+IntToStr(integer(NowMode))+#13); //设置发送模式
ATCMGS:
SendMessage(SendCode,SendContent);//编码并发送
ATCMGF3: //短信发送收到OK
begin
InOverLength:=false;
AddToResultSpool(SendID,0);//发送成功,记入结果队列
if NowMode<>DEFAULTMODE then
begin
if SendMessageQueue.AtLeast(1) then
SendStr('AT'+#13)
else
begin
NowMode:=DEFAULTMODE;
SendStr('AT+CMGF='+IntToStr(integer(NowMode))+#13); //设为缺省模式
end;
end
else
SendStr('AT'+#13); //
end;
AT2:
begin
InOverLength:=false;
SendStr('AT'+#13);
end;
end;
if FSendState=nowstate then
begin
ErrorTimes:=ErrorTimes+1;
end
else
begin
ErrorTimes:=0;
OverTime:=IncSecond(Now(),60);//所有命令60秒超时
end;
FSendState:=nowstate;
end;
procedure TShortMessage.SetRecvState(nowstate:RECVSTATE);
begin
FRecvState:=nowstate;
end;
procedure TShortMessage.Execute;
var
C : Char;
i:integer;
mode:SENDMODE;
pSendCode,PSendContent:array[0..500] of char;
//iLoop:integer;
LastSendTime:TDateTime;
begin
LastSendTime:=0;
//iLoop:=0;
while (not Terminated) do
begin
if port.CharReady then
begin //接收字符处理
C := port.GetChar;
if (C<>#13) and (C<>#10) then
RecvString:=RecvString+C;
if (C=#10) and (Length(RecvString)>0) then
begin //收到一行信息后对该行进行处理
DealReceivedLine(RecvString);
RecvString:='';
InReceivingLine:=false;
end
else
InReceivingLine:=true;
end;
//Inc(iLoop);
//if (iLoop>1000) then
if Now()>LastSendTime then
begin //到了允许的发送时间才发送短信,减少发送的速度,增加接收信息成功率
//iLoop:=0;
if (SendState=SENDIDLE) and (RecvState=RECVIDLE) and (not InReceivingLine) then
begin
if GetSMSFromSendSpool(pSendCode,pSendContent,SendID,SendTimes)=true then
begin
LastSendTime:=IncSecond(Now(),SendSpeed);//记下下次发送时间,保证一定时间间隔
SendCode:=AnsiString(pSendCode);
SendContent:=AnsiString(pSendContent);
mode:=TEXTMODE;
for i:=0 to Length(SendContent)-1 do
begin
if Ord(SendContent[i])>128 then
mode:=PDUMODE;
end;
if NowMode<>mode then
begin //发送模式有变化,需要改变发送模式
NowMode:=mode;
SendState:=ATCMGF2;
end
else //发送模式无变化,直接发送
begin
SendState:=ATCMGS;
end;
end;
end;
end;
if (SendState<>SENDIDLE) and (Now()>OverTime) then //每个命令周期不超过60秒
begin
if SendState=ATCMGS then //发送失败
begin
DoWhenSendFail();
SendState:=AT2; //By zqw 2008.7.31
//SendState:=ATCMGF3;
end
else if SendState=AT2 then
begin //发AT2超时则复位串口,应该能确保恢复正常,未测试
port.Open:=false;
port.Open:=true;
SendState:=AT;
end
else //其他命令则发AT
SendState:=AT2;
end;
Sleep(10);
end;
end;
//收到完整的一行后进行分析处理
procedure TShortMessage.DealReceivedLine(strReceivedLine:string);
var
strList:TStringList;
begin
AddToRecvSpool(strReceivedLine);
case RecvState of
RECVIDLE:
begin
if UpperCase(LeftStr(strReceivedLine,6))='+CSCA:' then
begin
strList:=SplitString(strReceivedLine,'"');
{CenterCode:=strList[1];
if CenterCode[1]='+' then
delete(CenterCode,1,1);}
strList.Free;
end
else if UpperCase(LeftStr(strReceivedLine,5))='+CMT:' then
begin
if Pos('"',strReceivedLine)>0 then
begin
strList:=SplitString(strReceivedLine,'"');
RecvCode:=strList[1];
RecvTime:=strList[3];
RecvTime:=LeftStr(RecvTime,17);
RecvTime:=StringReplace(RecvTime,',',' ',[rfReplaceAll]);
RecvTime:=StringReplace(RecvTime,'/','-',[rfReplaceAll]);
RecvTime:='20'+RecvTime;
strList.Free;
IsPDU:=false; //下一行不用PDU解码
end
else
begin
IsPDU:=true; //下一行用PDU解码
end;
RecvState:=CMT;
end
else if UpperCase(LeftStr(strReceivedLine,5))='OK' then
begin //正常情况OK下的流程
case SendState of
SENDIDLE:
;
AT:
SendState:=ATE0;
ATE0:
SendState:=ATCMGF;
ATCMGF:
//SendState:=ATCSCA;
SendState:=ATCNMI;//跳过原有读短信中心号码的步骤
ATCSCA:
SendState:=ATCNMI;//ATCMGD;
ATCMGD:
SendState:=SENDIDLE;//ATCNMI;
ATCNMI:
SendState:=ATCSAS;
ATCSAS:
SendState:=ATW;
ATW:
SendState:=SENDIDLE;
ATCMGF2:
SendState:=ATCMGS;
ATCMGS:
if( InOverLength ) then //还有未发完的超长短信
SendState:=ATCMGS
else
SendState:=ATCMGF3;
ATCMGF3:
SendState:=SENDIDLE;
AT2:
SendState:=SENDIDLE;
end; //case
end
else if UpperCase(LeftStr(strReceivedLine,5))='ERROR' then
begin
if SendState<>ATCMGS then
SendState:=SendState
else
begin
DoWhenSendFail();
SendState:=AT2;
end;
{end
else
begin
case SendState of
AT:
SendState:=ATE0;
end; //case}
end;
end; //IDLE
CMT: //收到短信内容
begin
if not IsPDU then
begin
RecvContent:=strReceivedLine;
if IsPDUFormat(RecvContent) then
RecvContent:=DecodeChinese(RecvContent);
end
else
begin
DecodePDU(strReceivedLine);
end;
AddSMSToRecvSpool(RecvCode,RecvTime,RecvContent);
RecvState:=RECVIDLE;
end; //CMT
end; //case
end;
procedure TShortMessage.SendStr(data:string);
begin
port.Output:=data;
AddToRecvSpool(data);
end;
procedure TShortMessage.AddToRecvSpool(LineStr:string);
var
pLine:^TLine;
begin
if RecvQueue.AtLeast(100) then
begin //控制队列的大小
pLine:=RecvQueue.Pop();
//FreeMem(pLine,sizeof(TLine));
Dispose(pLine);
end;
//pLine:=AllocMem(sizeof(TLine));
New(pLine);
pLine^.Content:=LineStr;
RecvQueue.Push(pLine);
end;
function TShortMessage.GetFromRecvSpool(pContent:pChar):boolean;
//type
// PString = ^string;
var
pLine:^TLine;
begin
try
if RecvQueue.AtLeast(1) then
begin
pLine:=RecvQueue.Pop();
//PString(Content)^:=pLine^.Content;
StrCopy(pContent,PChar(pLine^.Content));
//FreeMem(pLine,sizeof(TLine));
Dispose(pLine);
Result:=true;
end
else
Result:=false;
except
raise;
end;
end;
//待发的短信队列处理
procedure TShortMessage.AddSMSToSendSpool(Code,Content:PChar;Id:integer);
var
pMessage:^TMessage;
begin
//pMessage:=AllocMem(sizeof(TMessage));
New(pMessage);
pMessage^.ID:=Id;
pMessage^.Times:=0;
pMessage^.Code:=Code;
pMessage^.Content:=Content;
try
SendMessageQueue.Push(pMessage);
except
//FreeMem(pMessage,sizeof(TMessage));
Dispose(pMessage);
raise;
end;
end;
procedure TShortMessage.AddSMSToSendSpool(Code,Content:PChar;Id,Times:integer);
var
pMessage:^TMessage;
begin
//pMessage:=AllocMem(sizeof(TMessage));
New(pMessage);
pMessage^.ID:=Id;
pMessage^.Times:=Times;
pMessage^.Code:=Code;
pMessage^.Content:=Content;
try
SendMessageQueue.Push(pMessage);
except
//FreeMem(pMessage,sizeof(TMessage));
Dispose(pMessage);
raise;
end;
end;
function TShortMessage.GetSMSFromSendSpool(pCode,pContent:pChar;out Id,Times:integer):boolean;
//type
// PString = ^string;
var
pMessage:^TMessage;
begin
if SendMessageQueue.AtLeast(1) then
begin
pMessage:=SendMessageQueue.Pop();
//PString(Code)^:=pMessage^.Code;
ID:=pMessage.ID;
Times:=pMessage.Times;
StrCopy(pCode,PChar(pMessage^.Code));
//PString(Content)^:=pMessage^.Content;
StrCopy(pContent,PChar(pMessage^.Content));
//FreeMem(pMessage,sizeof(TMessage));
Dispose(pMessage);
Result:=true;
end
else
Result:=false;
end;
//收到的短信队列处理
procedure TShortMessage.AddSMSToRecvSpool(Code,Time,Content:string);
var
pMessage:^TMessage;
begin
//pMessage:=AllocMem(sizeof(TMessage));
New(pMessage);
pMessage^.Code:=Code;
pMessage^.Time:=Time;
pMessage^.Content:=Content;
RecvMessageQueue.Push(pMessage);
end;
function TShortMessage.GetSMSFromRecvSpool(pCode,pTime,pContent:pChar):boolean;
//type
// PString = ^string;
var
pMessage:^TMessage;
begin
try
if RecvMessageQueue.AtLeast(1) then
begin
pMessage:=RecvMessageQueue.Pop();
//PString(Code)^:=pMessage^.Code;
//PString(Time)^:=pMessage^.Time;
//PString(Content)^:=pMessage^.Content;
//Code:=pMessage^.Code;
StrCopy(pCode,PChar(pMessage^.Code));
//Time:=pMessage^.Time;
StrCopy(pTime,PChar(pMessage^.Time));
//Content:=pMessage^.Content;
StrCopy(pContent,PChar(pMessage^.Content));
//FreeMem(pMessage,sizeof(TMessage));
Dispose(pMessage);
Result:=true;
end
else
Result:=false;
except
raise;
end;
end;
//分割字符串函数
function TShortMessage.SplitString(const Source,ch:string):TStringList;
var
temp:String;
i:Integer;
begin
Result:=TStringList.Create;
//如果是空自符串则返回空列表
if Source=''
then exit;
temp:=Source;
i:=pos(ch,Source);
while i<>0 do
begin
Result.add(copy(temp,0,i-1));
Delete(temp,1,i);
i:=pos(ch,temp);
end;
Result.add(temp);
end;
procedure TShortMessage.SendMessage(Code,Content:string); //发送短信
function ExchangeCode(src:string):string;
var
strTmp:string;
srcLen:integer;
i:integer;
begin
strTmp := '';
srcLen := length(src);
if Odd(srcLen) then
src := src+'F';
i := 1;
while i<= srcLen do
begin
strTmp := strTmp + src[i+1]+src[i];
inc(i,2);
end;
ExchangeCode := strTmp;
end;
var
Widesms:WideString;
SendData:string;
HeadData:string;
strTmp:string;
strlen:integer;
begin
if NowMode=TEXTMODE then
begin
SendStr('AT+CMGS='+Code+#13);
SendStr(Content+^Z);
end
else if NowMode=PDUMODE then
begin
//------以下为老方法,需要短信中心号码,不能超长短信
{SendData := '0891';
strTmp := ExchangeCode(CenterCode);
SendData := SendData + strTmp;
SendData := SendData + '1100'+IntToHex(Length(Code),2)+'81';
strTmp := ExchangeCode(Code);
SendData := SendData + strTmp;
SendData := SendData + '0008A7';
Widesms := widestring(Content);
strTmp := EncodeChinese(Widesms);
strlen := length(strTmp) div 2;
SendData := SendData + IntToHex(strlen,2)+strTmp; //16进制数
strlen := (length(SendData) -18) div 2; //不包括开头前9个字节
HeadData := 'AT+CMGS='+IntToStr(strlen); //10进制数
SendStr(HeadData+#13);
SendStr(SendData+Chr(26));}
//--------以下为新方法,不需要短信中心号码,能自动发超长短信
Widesms := WideString(Content);
if( InOverLength ) then
begin //只针对未发完的信息进行处理
Inc(OverNo);
Delete(Widesms,1,(OverNo-1)*67);
Widesms:=LeftStr(Widesms,67);
SendData := '';
SendData := SendData + '005100'+IntToHex(Length(Code),2);
SendData := SendData +'81' + ExchangeCode(Code);
SendData := SendData + '0008A7';
strTmp := EncodeChinese(Widesms);
strTmp := '050003'+IntToHex(OverIdentify,2)+IntToHex(OverTotal,2)+IntToHex(OverNo,2)+strTmp;
strlen := Length(strTmp) div 2;
SendData := SendData + IntToHex(strlen,2)+strTmp; //16进制数
strlen := (length(SendData) -1) div 2; //不包括开头前9个字节
HeadData := 'AT+CMGS='+IntToStr(strlen); //10进制数
SendStr(HeadData+#13);
SendStr(SendData+Chr(26));
if( OverNo>=OverTotal ) then //发完了超长短信
InOverLength:=false;
end
else
begin
if( Length(Widesms)<=70 ) then
begin
InOverLength:=false;
SendData := '';
SendData := SendData + '001100'+IntToHex(Length(Code),2);
SendData := SendData +'81' + ExchangeCode(Code);
SendData := SendData + '0008A7';
strTmp := EncodeChinese(Widesms);
strlen := length(strTmp) div 2;
SendData := SendData + IntToHex(strlen,2)+strTmp; //16进制数
strlen := (length(SendData) -2) div 2; //不包括开头前1个字节
HeadData := 'AT+CMGS='+IntToStr(strlen); //10进制数
SendStr(HeadData+#13);
SendStr(SendData+Chr(26));
end
else
begin
//-------------- 过长第一次发前67个字
SendData := '';
SendData := SendData + '005100'+IntToHex(Length(Code),2);
SendData := SendData +'81' + ExchangeCode(Code);
SendData := SendData + '0008A7';
Randomize;
OverIdentify:=Random(100);
OverTotal:=(Length(Widesms)div 67)+1;
OverNo:=1;
InOverLength:=true;
//取前67个字
Widesms:=LeftStr(Widesms,67);
strTmp := EncodeChinese(Widesms);
strTmp := '050003'+IntToHex(OverIdentify,2)+IntToHex(OverTotal,2)+IntToHex(OverNo,2)+strTmp; //这一部分合计长度不大于280字节,协议用了12个字节,每个pdu编码字符需4个字节,故最大67个pdu编码字符
strlen := Length(strTmp) div 2;
SendData := SendData + IntToHex(strlen,2)+strTmp; //16进制数
strlen := (length(SendData) -1) div 2; //不包括开头前9个字节
HeadData := 'AT+CMGS='+IntToStr(strlen); //10进制数
SendStr(HeadData+#13);
SendStr(SendData+Chr(26));
end;
end;
end;
end;
procedure TShortMessage.DecodePDU(ReceivedLine:string);
var
i:Integer;
s,s1:String;
index_str,send_time_str,tel_str,content_str:String;
tel_len:Integer;
c:Char;
dcs:integer;
begin
//初始化
index_str:='';
send_time_str:='';
tel_str:='';
content_str:='';
s1:='';
s:=ReceivedLine;
//删除短信服务中心号码
delete(s,1,StrToInt('0x'+Copy(s,1,2))*2+2);
//删除文件头字节
delete(s,1,2);
//取得对方号码长度
tel_len:=StrToInt('0x'+Copy(s,1,2));
//删除对方号码长度字节和被叫号码类型字节
delete(s,1,4);
//取对方号码
if tel_len mod 2 = 0 then
begin
tel_str:=Copy(s,1,tel_len);
//删除对方号码
delete(s,1,tel_len);
end
else
begin
tel_str:=Copy(s,1,tel_len+1);
//删除对方号码
delete(s,1,tel_len+1);
end;
//将对方号码进行位移处理
for i:=1 to Length(tel_str) do
if i mod 2 = 0 then
begin
c:=tel_str[i];
tel_str[i]:=tel_str[i-1];
tel_str[i-1]:=c;
end;
//删除最后一位'F'
if tel_str[Length(tel_str)]='F' then
tel_str:=Copy(tel_str,1,Length(tel_str)-1);
RecvCode:=tel_str;
delete(s,1,2);
//取得编码方式
dcs:=StrToInt('0x'+Copy(s,1,2)); //dcs为0为纯英文编码,非0用中文编码
delete(s,1,2);
//取得发信日期
send_time_str:=Copy(s,1,14);
//将日期进行位移处理
send_time_str:='20'+send_time_str[2]+send_time_str[1]+'-'+send_time_str[4]+
send_time_str[3]+'-'+send_time_str[6]+send_time_str[5]+' '+send_time_str[8]+
send_time_str[7]+':'+send_time_str[10]+send_time_str[9]+':'+send_time_str[12]+
send_time_str[11];
//删除日期
delete(s,1,14);
RecvTime:=send_time_str;
//去掉回车键,换行键,"O","K"
i:=1;
while i<=Length(s) do
begin
if (s[i]=#13) or (s[i]=#10) or (s[i]='O') or (s[i]='K') then
begin
delete(s,i,1);
i:=1
end
else
i:=i+1;
end;
//删掉短信长度
delete(s,1,2);
//取得短信内容
while s<>'' do
begin
s1:='';
if Length(s)>=240 then
begin
s1:=Copy(s,1,240);
delete(s,1,240);
end
else
begin
s1:=Copy(s,1,Length(s));
delete(s,1,Length(s));
end;
if dcs<>0 then
content_str:=content_str+DecodeChinese(s1)
else
content_str:=content_str+DecodeEnglish(s1);
end;
RecvContent:=content_str;
end;
function TShortMessage.GetCountInSendMessageQueue():integer;
begin
if (SendState=ATCMGS) or (SendState=ATCMGF2) then
Result:=SendMessageQueue.Count+1
else
Result:=SendMessageQueue.Count;
end;
//根据经验判断str是否全部由PDU格式字符串组成
function TShortMessage.IsPDUFormat(str:string):boolean;
var
i,len:integer;
begin
len:=Length(str);
if len<6 then
begin //不够长肯定不是PDU
Result:=false;
Exit;
end;
Result:=true;
for i:=1 to len do
begin
if Pos(str[i],'0123456789ABCDEFGH')=0 then
begin //有字符不是16进制则肯定不是PDU
Result:=false;
Break;
end;
end;
end;
procedure TShortMessage.DoWhenSendFail();
begin
SendTimes:=SendTimes+1;
if SendTimes<3 then //放回发送队列等待重发
AddSMSToSendSpool(PChar(SendCode),PChar(SendContent),SendID,SendTimes)
else
AddToResultSpool(SendID,SendTimes);//发送失败,记入结果队列
end;
procedure TShortMessage.AddToResultSpool(ID,State:integer);
var
pResult:^TResult;
begin
//pMessage:=AllocMem(sizeof(TMessage));
New(pResult);
pResult^.ID:=ID;
pResult^.State:=State;
try
ResultQueue.Push(pResult);
except
Dispose(pResult);
raise;
end;
end;
function TShortMessage.GetFromResultSpool(out ID,State:integer):boolean; //获取发送结果
var
pResult:^TResult;
begin
try
if ResultQueue.AtLeast(1) then
begin
pResult:=ResultQueue.Pop();
ID:=pResult^.ID;
State:=pResult^.State;
Dispose(pResult);
Result:=true;
end
else
Result:=false;
except
raise;
end;
end;
end.
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Delphi
1
https://gitee.com/zqw/WefeelSMS.git
git@gitee.com:zqw/WefeelSMS.git
zqw
WefeelSMS
WefeelSMS
master

搜索帮助