📄 smscomm.pas
字号:
end;
end;
FDeleteSMSList.Clear;
end;
function TSMSComm.JudgeCMTI: Boolean;
var
ReadOK: Boolean;
S: string;
StartT,EndT: Single;
aAT_CMGR_Task: TAT_CMGR_Task;
begin
Result := False;
FCommQueue.GetByStr(S, -4);
if S <> '+CMTI' then Exit;
//有+CMTI标志
//期望获得+CMTI: "SM",xx#13#10
//把#13#10这个两个字节读到,从而可以解读出短信号xx
FillChar(FReceiveBuffer, FDATALEN, 0);
ReadOK:=False;
StartT:=(SysUtils.Time)*24*3600000;
repeat
if FShouldQuit then Exit;
EndT := (SysUtils.Time)*24*3600000;
if not FComPort.ReadStr(S,1) then Continue;
FCommQueue.AddByStr(S);
FCommQueue.GetOneByte(FReceiveBuffer[0],-1);
FCommQueue.GetOneByte(FReceiveBuffer[1],0);
if (FReceiveBuffer[0] = $0D) and (FReceiveBuffer[1] = $0A) then
begin
ReadOK:=True;
Break;
end;
//在2秒中内要读完
until (abs(EndT-StartT)>2000);
if not ReadOK then Exit;
//解读短信号
FReceiveBuffer[0] := 0;
FCommQueue.GetOneByte(FReceiveBuffer[0],-3);
if FReceiveBuffer[0] = Byte(',') then begin
FCommQueue.GetByStr(S,-2);
S := Copy(S,1,1);
end
else begin
FCommQueue.GetByStr(S,-3);
S := Copy(S,1,2);
end;
try
aAT_CMGR_Task := TAT_CMGR_Task.Create(ctNonBlocking);
aAT_CMGR_Task.SerialNo := StrToInt(S);
AddTask(aAT_CMGR_Task, atInsert, 0);
except
Exit;
end;
Result := True;
end;
// 打包用户数据的长度
function TSMSComm.GetChar(CC: Byte): string;
begin
FmtStr(Result,'%2.2X',[CC]);
end;
procedure TSMSComm.DoReceive(aSMSItem: TSMSItem);
begin
if Assigned( FOnReceiveSMS ) then begin
FSmartSMSThread.FEventType := etReceiveSMS;
FSmartSMSThread.FSMSItem := aSMSItem;
FSmartSMSThread.CallBackEvent;
end;
end;
procedure TSMSComm.DoBeforeSend(aSMSItem: TSMSItem);
begin
if Assigned( FOnBeforeSendSMS ) then begin
FSmartSMSThread.FEventType := etBeforeSendSMS;
FSmartSMSThread.FSMSItem := aSMSItem;
FSmartSMSThread.CallBackEvent;
end;
end;
procedure TSMSComm.DoAfterTimgingDelSMS;
begin
if Assigned( FOnAfterTimingDelSMS ) then begin
FSmartSMSThread.FEventType := etAfterTimingDelSMS;
FSmartSMSThread.CallBackEvent;
end;
end;
procedure TSMSComm.DoBeforeTimgingDelSMS;
begin
if Assigned( FOnBeforeTimingDelSMS ) then begin
FSmartSMSThread.FEventType := etBeforeTimingDelSMS;
FSmartSMSThread.CallBackEvent;
end;
end;
procedure TSMSComm.DoBeforeOpenModem;
begin
if Assigned( FOnBeforeOpenModem ) then begin
FSmartSMSThread.FEventType := etBeforeOpenModem;
FSmartSMSThread.CallBackEvent;
end;
end;
procedure TSMSComm.DoAfterOpenModem;
begin
if Assigned( FOnAfterOpenModem ) then begin
FSmartSMSThread.FEventType := etAfterOpenModem;
FSmartSMSThread.CallBackEvent;
end;
end;
procedure TSMSComm.DoAfterSend(aSMSItem: TSMSItem; SenOK: Boolean);
begin
if Assigned( FOnAfterSendSMS ) then begin
FSmartSMSThread.FEventType := etAfterSendSMS;
FSmartSMSThread.FSMSItem := aSMSItem;
FSmartSMSThread.FBool := SenOK;
FSmartSMSThread.CallBackEvent;
end;
end;
// 电话号码转换
function TSMSComm.CodeDestPhone(const DestPhone: string; var Len: integer): string;
var
TmpStr: string;
i: integer;
begin
Result := '';
case FDestPhoneStyle of
psMobilePhone: begin
TmpStr := '00000000000';
for i:=1 to min(Length(DestPhone),11) do TmpStr[i]:=DestPhone[i];
Result := '0011000D9168'+TmpStr[2]+TmpStr[1]+TmpStr[4]+TmpStr[3]
+TmpStr[6]+TmpStr[5]+TmpStr[8]+TmpStr[7]+TmpStr[10]+TmpStr[9]+'F'+TmpStr[11];
end;
psSpecialPhone: begin
FmtStr(Result,'%2.2X',[Length(DestPhone)]);
Result := '001100' + Result + '81';
if (Length(DestPhone) mod 2)=1 then
TmpStr := DestPhone + 'F'
else
TmpStr := DestPhone;
for i:=1 to (Length(TmpStr) div 2) do
Result := Result + TmpStr[i*2] + TmpStr[i*2-1];
end;
end;
case FEncodeStyle of
esUnicode: Result := Result + '000801';
esEightBit: Result := Result + '000401';
esSevenBit: Result := Result + '000001';
end;
Len := Length(Result) div 2;
end;
//将代码页为CP936的Unicode编码转换为GB2312的中文编码
function TSMSComm.DecodeChinese(Msg: string): string;
var
i,len,j:Integer;
t: string;
begin
Result:='';
len:=Length(Msg);
i:=1;
while i<=len do begin
t:=Copy(Msg,i,4);
j:=StrToInt('$'+t);
t:=widechar(j);
Result:=Result+t;
i:=i+4;
end;
end;
//7bit解码
function TSMSComm.DecodeSevenBit(Msg: string): string;
var
nSrc: Integer; // 源字符串的计数值
nByte: Byte; // 当前正在处理的组内字节的序号,范围是0-7
nLeft: Byte; // 上一字节残余的数据
begin
Result := '';
nSrc := 1; // 计数值初始化
// 组内字节序号和残余数据初始化
nByte := 0;
nLeft := 0;
// 将源数据每7个字节分为一组,解压缩成8个字节
// 循环该处理过程,直至源数据被处理完
// 如果分组不到7字节,也能正确处理
while nSrc<=Length(Msg) do begin
// 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节
Result := Result + Chr( ( (Byte(Msg[nSrc]) shl nByte) or nLeft ) and $7F );
// 将该字节剩下的左边部分,作为残余数据保存起来
nLeft := Byte(Msg[nSrc]) shr (7-nByte);
// 修改字节计数值
Inc(nByte);
// 到了一组的最后一个字节
if nByte = 7 then begin
// 额外得到一个目标解码字节
Result := Result + Chr(nLeft);
// 组内字节序号和残余数据初始化
nByte := 0;
nLeft := 0;
end;
// 修改计数值
Inc(nSrc);
end;
end;
//7bit编码
function TSMSComm.EncodeSevenBit(Msg: string): string;
var
nSrc: Integer; // 源字符串的计数值
nByte: Byte; // 当前正在处理的组内字节的序号,范围是0-7
nLeft: Byte; // 上一字节残余的数据
begin
Result := '';
nSrc := 0; // 计数值初始化
nByte := 0;
nLeft := 0;
// 将源串每8个字节分为一组,压缩成7个字节
// 循环该处理过程,直至源串被处理完
// 如果分组不到8字节,也能正确处理
while nSrc<Length(Msg) do begin
// 取源字符串的计数值的最低3位
nByte := nSrc and 7;
// 处理源串的每个字节
if nByte = 0 then
// 组内第一个字节,只是保存起来,待处理下一个字节时使用
nLeft := Byte(Msg[nSrc+1])
else begin
// 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节
Result := Result + Chr( (Byte(Msg[nSrc+1]) shl (8-nByte)) or nLeft );
// 将该字节剩下的左边部分,作为残余数据保存起来
nLeft := Byte(Msg[nSrc+1]) shr nByte;
end;
// 修改源串计数值
Inc(nSrc);
end;
if (Length(Msg)>0) and (nByte<>7) then
Result := Result + Chr(nLeft);
end;
// 内码转换
function TSMSComm.CodeMsg(const Msg: string; var DecodeLen: Integer): string;
var
i, Tollen, cur:Integer;
t: string;
TmpWideStr: WideString;
begin
Result:='';
case FEncodeStyle of
esUnicode: begin
TmpWideStr := Msg;
Tollen := Length(TmpWideStr);
i:=1;
while i<=Tollen do
begin
cur := ord(TmpWideStr[i]);
//BCD转换
FmtStr(t, '%4.4X', [cur]);
Result := Result+t;
inc(i);
end;
DecodeLen := Length(TmpWideStr)*2;
end;
esEightBit: begin
for i:=1 to Length(Msg) do
Result := Result + GetChar(Byte(Msg[i]));
DecodeLen := Length(Msg);
end;
esSevenBit: begin
t := EncodeSevenBit(Msg);
for i:=1 to Length(t) do
Result := Result + GetChar(Byte(t[i]));
DecodeLen := Length(t);
end;
end;
end;
function TSMSComm.GSM_AT_CMGS(const DestPhone: string; const Msg: string): Boolean;
var
aTAT_CMGS_Task: TAT_CMGS_Task;
aSMSItem: TSMSItem;
begin
Result := False;
if (not FActive) or (DestPhone='') or (Msg='') then Exit;
if InCommThread or FInSync then begin
FillChar( aSMSItem, Sizeof(TSMSItem), 0 );
aSMSItem.DestPhone := DestPhone;
aSMSItem.Msg := Msg;
Result := _GSM_AT_CMGS(aSMSItem);
end
else begin
if FTaskCapacity>0 then begin
if TaskList.Count>=FTaskCapacity then Exit;
end;
aTAT_CMGS_Task := TAT_CMGS_Task.Create(ctBlocking);
try
aTAT_CMGS_Task.SMSItem.DestPhone := DestPhone;
aTAT_CMGS_Task.SMSItem.Msg := Msg;
AddTask(aTAT_CMGS_Task, atInsert, 0);
while not aTAT_CMGS_Task.Finish do Application.ProcessMessages;
Result := aTAT_CMGS_Task.Success;
finally
FreeAndNil(aTAT_CMGS_Task);
end;
end;
end;
// 发送消息
function TSMSComm._GSM_AT_CMGS(aSMSItem: TSMSItem): Boolean;
// 内部发送消息
function Send(const DestPhone: string; const Msg: string): Boolean;
var
i, j, k, DataLen, UserDataLen: integer;
LengthStr: string[3];
S, Headinf, DataPad, InCodedMsg, InCodedDestPhone: string;
ReadOK: Boolean;
StartT,EndT: Single;
begin
Result := False;
UserDataLen := Length(Msg);
if (not FActive) or (DestPhone = '') or (UserDataLen = 0) then Exit;
InCodedMsg := CodeMsg(Msg, UserDataLen);
InCodedDestPhone := CodeDestPhone(DestPhone, j);
DataLen := UserDataLen + j; //用户数据+包头字节
i := DataLen div 100;
LengthStr[0] := Char(i+$30);
j := (DataLen-100*i) div 10;
LengthStr[1]:= Char(j+$30);
k := (DataLen-100*i-10*j);
LengthStr[2]:= Char(k+$30);
Headinf :=''; DataPad:='';
Headinf := 'AT+CMGS='+LengthStr[0]+LengthStr[1]+LengthStr[2]+#13;
if FEncodeStyle = esSevenBit then
DataPad := InCodedDestPhone + GetChar(Length(Msg))
else
DataPad := InCodedDestPhone + GetChar(UserDataLen);
DataPad := DataPad + InCodedMsg + #26;
if not FComPort.WriteStr(Headinf) then Exit;
FCommQueue.Reset;
FillChar(FReceiveBuffer, 256, 0);
ReadOK:=False;
StartT:=(SysUtils.Time)*24*3600000;
repeat
EndT := (SysUtils.Time)*24*3600000;
if not FComPort.ReadStr(S, 1) then Continue;
FCommQueue.AddByStr(S);
if JudgeCMTI then Exit;
FCommQueue.GetOneByte(FReceiveBuffer[0],-2);
FCommQueue.GetOneByte(FReceiveBuffer[1],-1);
FCommQueue.GetOneByte(FReceiveBuffer[2],0);
if (FReceiveBuffer[0] = $0D) and (FReceiveBuffer[1] = $0A) and
(FReceiveBuffer[2] = Byte('>')) then
begin
ReadOK:=True;
Break;
end;
until (abs(EndT-StartT)>5000); //在5秒中内要读完
if not ReadOK then Exit;
if not FComPort.WriteStr(DataPad) then Exit;
FCommQueue.Reset;
FillChar(FReceiveBuffer, FDATALEN, 0);
ReadOK:=False;
StartT:=(SysUtils.Time)*24*3600000;
repeat
EndT := (SysUtils.Time)*24*3600000;
if not FComPort.ReadStr(S, 1) then Continue;
FCommQueue.AddByStr(S);
if JudgeCMTI then Exit;
FCommQueue.GetOneByte(FReceiveBuffer[0],-4);
FCommQueue.GetOneByte(FReceiveBuffer[1],-3);
FCommQueue.GetOneByte(FReceiveBuffer[2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -