⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smscomm.pas

📁 短信二次开发控件SMSComm
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    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 + -