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

📄 sms_pudunit.pas

📁 用串口通信实现手机短信的收发的例子(带源码)
💻 PAS
📖 第 1 页 / 共 3 页
字号:
      // 将该字节剩下的左边部分,作为残余数据保存起来
      nLeft := Byte(pSrc[i]) shr nChar;
      // 修改目标串的指针和计数值 pDst++;
     // nDst++;
    end;

    // 修改源串的指针和计数值
    Inc(i);
    Inc(nSrc);
  end;

  // 返回目标串
  Result := pDst;
end;

// 7-bit解码
// pSrc: 源编码串指针
// nSrcLength: 源编码串长度
// 返回: 目标字符串

function gsmDecode7bit(pSrc:string; nSrcLength:Integer):string;
var
  nSrc:Integer; // 源字符串的计数值
  nByte:Integer; // 当前正在处理的组内字节的序号,范围是0-6
  nLeft:Byte; // 上一字节残余的数据
  tmpChar:Byte;
  pDst:string;

begin

  // 计数值初始化
  nSrc := 1;

  // 组内字节序号和残余数据初始化
  nByte := 0;
  nLeft := 0;
  pdst := '';
  // 将源数据每7个字节分为一组,解压缩成8个字节
  // 循环该处理过程,直至源数据被处理完
  // 如果分组不到7字节,也能正确处理
  while (nSrc < nSrcLength) do
  begin
    tmpChar := byte(StrToInt('$' + pSrc[nsrc] + pSrc[nsrc + 1]));
    // 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节
    pDst := pDst + Char(((tmpchar shl nByte) or nLeft) and $7F);
    // 将该字节剩下的左边部分,作为残余数据保存起来
    nLeft := tmpChar shr (7 - nByte);

    // 修改字节计数值
    Inc(nByte);

    // 到了一组的最后一个字节
    if (nByte = 7) then
    begin
      // 额外得到一个目标解码字节
      pdst := pDst + Char(nLeft);

      // 组内字节序号和残余数据初始化
      nByte := 0;
      nLeft := 0;
    end;

    // 修改源串的指针和计数值

    nSrc := nSrc + 2;
  end;
  // 返回目标串长度
  result := pdst;
end;

constructor TSMSPDUproc.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
  FCurrSMSIndex:=0;
  FTP_DCS := tdUCS2;
  FTP_DA := '';
  FSMSC := '';
  SetLength(Ftp_udbyte, 140);
  FTP_UDStr := '';
  FBaudRate := 4800;
  SMScomm := TComm.Create(Self);
  SMScomm.OnReceiveData := SMSReceiveData;
  FActive := False;
  CurrState := NORMAL;
  OTTimer := TTimer.Create(Self);
  OTTimer.Interval := 100;
  OTTimer.OnTimer := OTTimerTimer;
end;

procedure TSMSPDUproc.DecodePUD(s: string);
var
smsclen,PhoneIDLen,InfoLen:integer;
tmp:string;
cpos:Integer;
mSMSC,mPhoneID,mInfo:string;
mGTime:TDateTime;
mType:TTP_DCS;
begin
mSMSC:='';
mPhoneID:='';
mInfo:='';
mType:=tdUCS2;
//08 地址信息的长度 个八位字节(包括91)
cpos:=1;
//消息中心长度
smsclen:=StrToInt('$'+MidStr(s,cpos,2));
//91 SMSC地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
//68 31 08 20 05 05 F0 SMSC地址 8613800250500,补‘F’凑成偶数个
if smsclen=0 then
  cpos:=cpos+2
else
begin
  cpos:=cpos+4;   //略去91;
  tmp:=MidStr(s,cpos,smsclen*2-2);
  mSMSC:=ResumeOrder(tmp);
  cpos:=cpos+smsclen*2-2;
end;
//84 基本参数(TP-MTI/MMS/RP) 接收,无更多消息,有回复地址
cpos:=cpos+2;
//0D 回复地址数字个数 共13个十进制数(不包括91和‘F’)
PhoneIDLen:=StrToInt('$'+MidStr(s,cpos,2));
if (PhoneIDLen mod 2)>0 then Inc(PhoneIDLen);
cpos:=cpos+2;
//91 回复地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
//68 31 58 81 27 64 F8 回复地址(TP-RA) 8613851872468,补‘F’凑成偶数个
if PhoneIDLen=0 then
  cpos:=cpos+2
else
begin
  cpos:=cpos+2;
  tmp:=MidStr(s,cpos,PhoneIDLen);
  mPhoneID:=ResumeOrder(tmp);
  cpos:=cpos+PhoneIDLen;
end;
//00 协议标识(TP-PID) 是普通GSM类型,点到点方式
cpos:=cpos+2;
//08 用户信息编码方式(TP-DCS) UCS2编码
case StrToInt(MidStr(s,cpos,2)) of
  0:
    mType:= td7_Bit;
  8:
    mtype:=tdUCS2;
  15:
    mType:=td8_Bit;
end;
cpos:=cpos+2;
//30 30 21 80 63 54 80 时间戳(TP-SCTS) 2003-3-12 08:36:45  +8时区
tmp:=MidStr(s,cpos,14);
tmp:=ChangeLeftAndRight(tmp);
mGTime:=StrToDate(MidStr(tmp,1,2)+'-'+MidStr(tmp,3,2)+'-'+MidStr(tmp,5,2));

mGTime:=mGTime+ StrToTime(MidStr(tmp,7,2)+':'+MidStr(tmp,9,2)+':'+MidStr(tmp,11,2));
cpos:=cpos+14;
//06 用户信息长度(TP-UDL) 实际长度6个字节
InfoLen:=StrToInt('$'+MidStr(s,cpos,2));
cpos:=cpos+2;
//4F 60 59 7D 00 21 用户信息(TP-UD) “你好!”

if InfoLen>0 then
begin
  tmp:=MidStr(s,cpos,InfoLen*2);
  case mType of
    td7_Bit:
        mInfo:=gsmDecode7bit(tmp,InfoLen*2);
    td8_Bit:
        ;
    tdUCS2:
        mInfo:=UniCodeToGB5(tmp);
  end;
end;

if Assigned(fonReceiveSMS ) then
  FOnReceiveSMS(Self,mSMSC,mPhoneID,mInfo,mGTime);



end;

destructor TSMSPDUproc.Destroy;
begin
  SMScomm.Free;
  inherited;

end;
/// <summary>
/// 取处理过后的PUD字符串
/// </summary>
/// <returns> PUD字符串 </returns>
function TSMSPDUproc.getPUDStr:string;
var
  mPudStr:string;
  tmp, s:string;
  tmp2:PChar;
  len:integer;
begin

  len := Length(FSMSC);
  //08 SMSC地址信息的长度 共8个八位字节(包括91)
  //91 SMSC地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
  //68 31 08 20 05 05 F0 SMSC地址 8613800250500,补‘F’凑成偶数个
  if len > 0 then
  begin
    tmp := '91' + ChangeLeftAndRight(FSMSC);
    len := Length(tmp) div 2;
  end;

  fmtstr(s, '%2.2D', [len]);
  mPudStr := s + tmp;

  //11 基本参数(TP-MTI/VFP) 发送,TP-VP用相对格式
  //00 消息基准值(TP-MR) 0
  mPudStr := mPudStr + '1100';

  //0D 目标地址数字个数 共13个十进制数(不包括91和‘F’)
  FmtStr(s, '%2.2X', [Length(FTP_DA)]);

  //91 目标地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
  //68 31 58 81 27 64 F8 目标地址(TP-DA) 8613851872468,补‘F’凑成偶数个
  mPudStr := mPudStr + s + '91' + ChangeLeftAndRight(FTP_DA);

  //00 协议标识(TP-PID) 是普通GSM类型,点到点方式
  mPudStr := mPudStr + '00';

  //00 用户信息编码方式(TP-DCS) 7-bit编码
  //00 有效期(TP-VP) 5分钟
  //06 用户信息长度(TP-UDL) 实际长度6个字节
  //C8 32 9B FD 0E 01 用户信息(TP-UD) “Hello!”
  case FTP_DCS of
    td7_Bit:
      begin
        if Length(AnsiString(FTP_UDStr))>160 then
        begin
          GetMem(tmp2,160);
          StrLCopy(tmp2,PAnsiChar(FTP_UDStr),160);
          FTP_UDStr:=tmp2;
          FreeMem(tmp2);
        end;
        mPudStr := mPudStr + '0000'; //tp-dcs + tp-vp
        fmtstr(s, '%2.2X', [Length(FTP_UDStr)]);
        mpudstr := mpudstr + s; //tp-udl
        mpudstr := mpudstr + gsmEncode7bit(Ftp_udstr, Length(FTP_UDStr)); //tp-ud
      end;

    td8_Bit:
      begin
        mPudStr := mPudStr + '1500'; //tp-dcs + tp-vp
      end;
    tdUCS2:
      begin
        if Length(widestring(FTP_UDStr))>70 then
        begin
          GetMem(tmp2,140);
          StrLCopy(tmp2,PAnsiChar(FTP_UDStr),140);
          FTP_UDStr:=tmp2;
          FreeMem(tmp2);
        end;
        mPudStr := mPudStr + '0800';
        tmp := GB5ToUniCode(FTP_UDStr);
        FmtStr(s, '%2.2X', [Length(tmp) div 2]);
        mPudStr := mPudStr + s; //tp-udl
        mPudStr := mPudStr + tmp;
      end;
  else
    begin
      mPudStr := mPudStr + '0800';
      tmp := GB5ToUniCode(FTP_UDStr);
      FmtStr(s, '%2.2X', [Length(tmp) div 2]);
      mPudStr := mPudStr + s; //tp-udl
      mPudStr := mPudStr + tmp;
    end;
  end;

  if len > 0 then
    FmtStr(FCMGSLen, '%3.3D', [Length(mPudStr) div 2 - len - 1])
  else
    FmtStr(FCMGSLen, '%3.3D', [Length(mPudStr) div 2 - 1]);
  FPUDStr:=mPudStr;
  Result := mPudStr;
end;
//初始化模块,发送ATE测试模块连接是否正常



procedure TSMSPDUproc.OTTimerTimer(Sender:TObject);
begin
  Inc(tver);
  if tver > 50 then //等待回码超时的处理
  begin
    tver := 0;
    case CurrState of
      NORMAL:
        ;
      ATE:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm('ate' + #$D);
          end
          else //超过3次报错
          begin;
            ReSendCount := 0;
            OnError(Self,'ATE发送错误');
          end;
        end;
      ATCMGF:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm('at+cmgf=0' + #$D);
          end
          else //超过3次报错
          begin
            ReSendCount := 0;
            OnError(Self,'AT+CMGF发送错误');
          end;
        end;
      ATCNMI:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm('at+cnmi=2,1,0,0,0' + #$D);
          end
          else //超过3次报错
          begin
            ReSendCount := 0;
            OnError(Self,'AT+CNMI发送错误')
          end;
        end;
      ATCMGS_1:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm('at+cmgs='+ FCMGSLen +#$D);
          end
          else //超过3次报错
          begin
            ReSendCount := 0;
            OnError(Self,'AT+CMGS_1发送错误');
          end;
        end;
      ATCMGS_2:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm(FPUDStr+#$1A);
          end
          else //超过3次报错
          begin
            ReSendCount := 0;
            OnError(self,'AT+CMGS_2发送错误');
          end;
        end;
      ATCMGR:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm('at+cmgr='+inttostr(FCurrSMSIndex)+#$D);
          end
          else //超过3次报错
          begin
            ReSendCount := 0;
            OnError(self,'AT+CMGR发送错误');
          end;
        end;
      ATCMGD:
        begin
          if ReSendCount < 2 then //重发次数少于3次
          begin
            sendStrToComm('at+cmgd='+inttostr(FCurrSMSIndex)+#$D);
          end
          else //超过3次报错
          begin
            ReSendCount := 0;
            OnError(self,'AT+CMGD发送错误');
          end;

        end;
    end;
    OnError(Self,'通讯超时');
    tver:=0;
    OTTimer.Enabled:=False;
  end;
end;

procedure TSMSPDUproc.resetSMS;
begin
  CurrState := ATE;
  ReSendCount := 0;
  sendStrToComm('ate' + #$D);
end;

procedure TSMSPDUproc.SendSM;
begin
  ReSendCount:=0;
  getPUDStr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -