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

📄 txmobile.~pas

📁 访问西门子手机,可发送AT指令,并进行解码和加码.
💻 ~PAS
📖 第 1 页 / 共 2 页
字号:
//  作    者 : 王建东
//  创建时间 : 2003-9-26
//  备    注 : TMobile类用于接入西门子手机

unit TXMobile;

interface

uses
   SyncObjs,Windows,SysUtils,Outputunit,Dialogs;
const
 ReceiveBufLength  = 200  ;
 ReadBufLength      = 4000 ;   // 读出缓冲大小

type
 TReceiveMsg = Record          //接收短信记录类型
       dtReceiveTime   : TDatetime;
       strSourceMobile : String  ;
       strContent      : String  ;
       nIndex          : Integer ;
 end;

 TReceiveBuf  = Array [0.. ReceiveBufLength -1  ] of TReceiveMsg ;
 TReadBuf     = Array [0..ReadBufLength -1] of Char;  // 读的缓冲区数组类型

 TMobile = Class
      constructor Create ;
    public
      function  OpenComm( strComName : string  ) : Boolean ;  //  打开端口
      procedure CloseComm ;      //  关闭端口
      function  SetDCB( DCB1  : TDCB ) : Boolean;
      function  GetDCB : TDCB ;
      procedure SetSCA( _SCA : String ) ;

      function SendMsg(strTargetMobile : String ; strContent : string ) : Boolean ;
      function ReceiveMessage( var ReceiveBuf : TReceiveBuf ) : Integer ; // 返回接收的个数
      function TestAtCommand( AtCommand : String ) : String;
      function ReadBuf : Ansistring;
    protected
      // 与串口通信有关的变量
      DCB : TDCB ;                           // 串口通信参数设置
      CommTimeOut : TCOMMTIMEOUTS ;          // 读写时延设置
      WriteEndEvent,ReadEndEvent : TEvent;   // WriteEndEvent 写完事件,ReadEndEvent 读完事件
      CommHandle : THandle ;
      bConnected : Boolean;

      //以下为短信相关资料
      strSMAddress : String  ;              // 短信中心地址
      strTypeOfSCA : String  ;              // 短信中心地址类型
      strTypeOfOA  : String  ;              // 被叫号码的类型
      function GetMsg(var MsgBuf : TReadBuf ): TReceiveMsg ;  // 从pdu短信报文取出短信
      function ConvertPhoneNum(strNum:string):string ;        // 反转手机号码
      function MakePDU(DestNumber,Content,SCAddress:String;   // 产生PDU报文
                       Result_String:pchar ; var LenOfSCA : DWORD ):Bool ;
      function SMSEncode(s:WideString;Result_Code:pchar):Bool ;

      function ConvertDeliverAddress(strAddress : string ) : String;
 end;
implementation
uses
  IniFiles;
constructor TMobile.Create ;
var
  IniFile : TIniFile ;
begin
  // 读入硬件通信参数
  IniFile := TIniFile.Create(GetCurrentDir + '\Mobile.ini');
  self.DCB.BaudRate  := IniFile.ReadInteger('Siemens','DCB_BaudRate',9600);
  self.DCB.ByteSize  := IniFile.ReadInteger('Siemens','DCB_ByteSize',8);
  self.DCB.Parity    := IniFile.ReadInteger('Siemens','DCB_Parity',0);
  self.DCB.StopBits  := IniFile.ReadInteger('Siemens','DCB_StopBits',0);

  self.CommTimeOut.ReadIntervalTimeout := 0;
  self.CommTimeOut.ReadTotalTimeoutMultiplier := 0 ;
  self.CommTimeOut.ReadTotalTimeoutConstant   := IniFile.ReadInteger('Siemens','ReadTimeoutConstant',3000);
  self.CommTimeOut.WriteTotalTimeoutMultiplier:= 0 ;
  self.CommTimeOut.WriteTotalTimeoutConstant  := IniFile.ReadInteger('Siemens','WriteTimeoutContant',3000);
  WriteEndEvent := TEvent.Create(nil,True,False,'WriteEnd');
  ReadEndEvent  := TEvent.Create(nil,True,False,'ReadEnd');

  // 读入PDU报文相关信息
  self.strSMAddress  := Trim(IniFile.ReadString('SendModule1','SCA','8613800759500'));
  self.strTypeOfSCA  := Trim(IniFile.ReadString('SendModule1','TypeOfSCA','91'));
  self.strTypeOfOA   := Trim(self.strTypeOfSCA);


  self.bConnected    := FALSE;
end;
function TMobile.OpenComm( strComName : string  ) : Boolean ;
var
  DCB1 : TDCB;
  fRetVal : Boolean;
begin

  CommHandle := CreateFile(PChar(strComName),
                    GENERIC_READ or GENERIC_WRITE,
                    0,
                    nil,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);

  if CommHandle = INVALID_HANDLE_VALUE then
           begin
              Result := FALSE; //  ('GPS串口连接失败');
              exit;
           end;

  SetCommTimeouts(CommHandle, CommTimeOut);

  GetCommState(CommHandle,DCB1);
  DCB1.BaudRate := DCB.BaudRate   ;      // 播特率
  DCB1.ByteSize := DCB.ByteSize   ;      // 数据位
  DCB1.Parity   := NoParity    ;        // 奇偶校验
  DCB1.StopBits := DCB.StopBits   ;      // 停止位
  DCB := DCB1;
  fRetVal := SetCommState(CommHandle, DCB);
  if (fRetVal) then
      bConnected := TRUE
    else
      begin
          Result := False;
          bConnected := FALSE;
          CloseHandle(CommHandle);
          Exit;
      end;
  Result := True;

end;
procedure  TMobile.CloseComm ;
begin
  try
     CloseHandle(self.CommHandle);
     bConnected := False;
  except
     on EExternalException do WriteDbg('TMobile.CloseComm   -- 关闭失败 ');
   end;
end;
function TMobile.SendMsg(strTargetMobile : String ;
                          strContent : string ) : Boolean ;
var
  Buf : TReadBuf ;
  PDUCode : AnsiString;

  nLen,nWriteRet,nReadRet,nCodeLen,nLenOfSCA : DWord;
  str1,strRet : string;
  Overlapped: TOverlapped ;
  bRet : Boolean;
begin
  WriteDbg('TMobile.SendMsg --  In ');
  FillChar(Buf,ReadBufLength,0);
  if MakePDU(strTargetMobile,strContent,strSMAddress,Buf,nLenOfSCA ) = True then
    begin
     PDUCode  := strpas(buf);
     nCodeLen := (Length(PDUCode) div 2)- nLenOfSCA -1 ;  // 长度要除去短信中心号码长度
    end
   else
    begin
     Result := False;
     Exit;
    end;

  // 写入AT+CMGS 命令
  WriteDbg('SendMsg  :  写入AT+CMGS 命令 ' );
  str1 := 'AT+CMGS=' + IntToStr(nCodeLen)+ #13;
  nLen := Length(str1);
  FillChar(Buf,ReadBufLength,0);
  StrPCopy(Buf,str1);
  Overlapped.hEvent := WriteEndEvent.Handle;
  WriteEndEvent.ResetEvent ;
  WriteFile(CommHandle,Buf,nLen,nWriteRet,@Overlapped);
  bRet := GetOverlappedResult(CommHandle,Overlapped,nWriteRet,True);
  if ( nLen <> nWriteRet )  then  // 写入长度不对
  begin
    WriteDbg('SendMsg :  写入长度不对 ... ');
    Result := FALSE;
    Exit;
  end;
  if ( bRet = False ) then        // 调用GetOverlappedResult 失败
    begin
      WriteDbg('SendMsg : 调用GetOverlappedResult 失败');
      Result := FALSE ;
      Exit;
    end;
  WriteEndEvent.ResetEvent ;

  // 读出写入命令结果
  WriteDbg('SendMsg  : 读出写入命令结果 ' );
  Overlapped.hEvent := self.ReadEndEvent.Handle;
  ReadEndEvent.ResetEvent;
  FillChar(Buf,ReadBufLength,0);
  ReadFile(CommHandle,Buf,1000,nReadRet,@Overlapped);
  bRet := GetOverlappedResult(CommHandle,Overlapped,nReadRet,True);
  if ( bRet = False ) then
    begin
      WriteDbg('TMobile.SendMsg -- 调用GetOverlappedResult 失败');
      Result := FALSE;
      Exit;
    end;
  ReadEndEvent.ResetEvent ;
  WriteDbg('读出写入命令结果 = ' + strpas(Buf)) ;

  // 写入PDU编码
  WriteDbg('SendMsg  : 写入PDU编码 -- ' + PDUCode  );
  str1 := PDUCode + #26;
  nLen := Length(str1);
  FillChar(Buf,ReadBufLength,0);
  StrPCopy(Buf,str1);
  Overlapped.hEvent := WriteEndEvent.Handle;
  WriteEndEvent.ResetEvent ;
  WriteFile(CommHandle,Buf,nLen,nWriteRet,@Overlapped);
  bRet := GetOverlappedResult(CommHandle,Overlapped,nWriteRet,True);
   if ( bRet = False ) then
    begin
      Result := FALSE;
      Exit;
    end;
  FillChar(Buf,ReadBufLength-1,0);
  WriteEndEvent.ResetEvent ;

  // 读出写入PDU编码结果
  WriteDbg('TMobile.SendMsg  --  读出写入PDU编码结果 ' );
  Overlapped.hEvent := self.ReadEndEvent.Handle;
  ReadEndEvent.ResetEvent;
  FillChar(Buf,ReadBufLength,0);
  ReadFile(CommHandle,Buf,1000,nReadRet,@Overlapped);
  bRet := GetOverlappedResult(CommHandle,Overlapped,nReadRet,True);
  if ( bRet = False ) then
     begin
       Result := FALSE;  //  GetOverlappedResult 调用失败 !');
       Exit;
     end;
  ReadEndEvent.ResetEvent ;
  WriteDbg('TMobile.SendMsg -- 读出写入PDU编码结果 Content:' + StrPas(Buf) +
           ',Length :' + IntToStr(nReadRet) );

   // 读出发送结果
  ReadEndEvent.ResetEvent;
  FillChar(Buf,ReadBufLength,0);
  ReadFile(CommHandle,Buf,1000,nReadRet,@Overlapped);
  bRet := GetOverlappedResult(CommHandle,Overlapped,nReadRet,True);
  if ( bRet = False ) then
    begin
       Result := FALSE;  //  GetOverlappedResult 调用失败 !');
       Exit;
    end;
  ReadEndEvent.ResetEvent ;
  WriteDbg('TMobile.SendMsg -- 读出发送结果 Content:' + StrPas(Buf) +',Length :' + IntToStr(nReadRet) );

  strRet := Copy(buf,3,5) ;
  if ( strRet = '+CMGS') then
  begin
    Result := True ;
    WriteDbg('TMobile.SendMsg -- Succeed to Send ||'+ strRet);
  end
  else
  begin
    Result := FALSE;
    WriteDbg('TMobile.SendMsg -- Fail to Send ||'+strRet);
  end;
  WriteDbg('TMobile.SendMsg --  Out ');

end;
function TMobile.GetMsg(var MsgBuf : TReadBuf ): TReceiveMsg ;
var
  i,j,z,k,nOctetNum,nSCALen,nFirstOctetPos,nAddressFieldLen,
  nDataLen,nPIDPos,nIndexEnd : Integer ;
  nDCS,PreByte,CurByte: Byte ; // 编码方式
  strLen,strAddressFieldLen,strDCS,strDataLen,strData,
  str1,strIndex: string ;
  DataBuf : Array [0..3000] of char ;
  wc : WideChar ;
  dw,nAddrTail : DWord    ;
begin
//   showmessage(strpas(msgbuf));
   i:= 0 ;
   while ( i<= 100 ) do            // 求短信的索引号
    if MsgBuf[i] = ',' then
        break
       else
        Inc(i,1);
   nIndexEnd := i -1 ;
   if nIndexEnd >=  7 then
     begin
       strIndex := '';
       for i:= 7 to nIndexEnd do
         strIndex := strIndex + MsgBuf[i];
       Result.nIndex := StrToInt(strIndex);
     end
     else
     begin
       Result.nIndex := -1 ;
     end;

   i:= 0;
   while ( i<= 3000 ) do
    if MsgBuf[i] = #13 then
       Break
      else
       Inc(i,1);
   Inc(i,1);
   strLen := MsgBuf[i+1] +MsgBuf[i+2];
   nSCALen := StrToInt('$'+strLen);
   nFirstOctetPos := i + 2 + nSCALen * 2 + 1 ;  // 文件头位置

   strAddressFieldLen := MsgBuf[nFirstOctetPos + 2] + MsgBuf[nFirstOctetPos+3];
   nAddressFieldLen   := StrToInt('$'+strAddressFieldLen);
   if nAddressFieldLen >  2 then
      begin
        Result.strSourceMobile := '';
        if ( nAddressFieldLen mod 2 = 0 ) then
            nAddrTail := 0
           else
            nAddrTail := 1 ;
        for j:= nFirstOctetPos + 6 to  nFirstOctetPos + 6 +nAddressFieldLen -1 + nAddrTail do
          Result.strSourceMobile := Result.strSourceMobile + MsgBuf[j];
        Result.strSourceMobile := ConvertDeliverAddress(Result.strSourceMobile);
      end
   else
      Result.strSourceMobile := '5555';

   if ( nAddressFieldLen mod 2 ) = 1 then
     begin
      strDCS  := MsgBuf[nFirstOctetPos + 6 + nAddressFieldLen + 3 ]+
                 MsgBuf[nFirstOctetPos + 6 + nAddressFieldLen + 4 ];
      nPIDPos := nFirstOctetPos + 6 + nAddressFieldLen +1 ;
     end
    else
     begin
      strDCS := MsgBuf[nFirstOctetPos + 6 + nAddressFieldLen + 2 ]+
                MsgBuf[nFirstOctetPos + 6 + nAddressFieldLen + 3 ] ;
      nPIDPos := nFirstOctetPos + 6 + nAddressFieldLen ;
     end;

   strDataLen := MsgBuf[nPIDPos + 18] + MsgBuf[nPIDPos + 19] ;
   nDataLen   := StrToInt('$'+strDataLen);
   nDCS       := StrToInt('$'+strDCS);
   if  ( nDCS and 12 )  = 8 then   //   用于判断编码方式
     begin
      // unicode 编码 ( 16 bit)
      FillChar(DataBuf,3001,0);
      for j := 0 to  nDataLen * 2 -1  do
        DataBuf[j] := MsgBuf[j + nPIDPos + 20 ];

      strData := '';
      for J := 0 to nDataLen div 2 - 1 do
       begin
         str1:= DataBuf[j * 4 ]+DataBuf[j* 4 +1]+DataBuf[j* 4 +2]+
                DataBuf[j* 4 +3];
         dw  := StrToInt('$'+str1);
         wc  := WideChar(dw);
         strData := strData+ wc;
       end;
     end
    else
    if ( nDCS and 12 = 4 ) then //  8位编码规则
     begin
       FillChar(DataBuf,3001,0);
       nOctetNum := nDataLen ;
       for j:= 0 to nOctetNum - 1 do
         DataBuf[j] := Chr( StrToInt('$' + MsgBuf[j*2+nPIDPos + 20] + MsgBuf[j*2 + nPIDPos + 20 + 1] ));

       strData := '';
       for j:=0 to nOctetNum -1 do
             strData := strData + DataBuf[j] ;
     end
    else
    if ( nDCS and 12 = 0 ) then           // 7 位编码规则
     begin
       FillChar(DataBuf,3001,0);
       if  (( nDataLen * 7 ) mod 8 )  = 0 then
         nOctetNum :=  nDataLen * 7 div 8
       else
         nOctetNum :=  nDataLen * 7 div 8 + 1 ;

       For j:= 0 to   nOctetNum  -1 do   // 取出用户数据
         DataBuf[j] :=Chr(StrToInt('$'+MsgBuf[j*2+nPIDPos+20]+
                                       MsgBuf[j*2+nPIDPos+20+1] ));

       strData := '';
       for j:= 0 to nOctetNum -1 do
       begin
          k := (j + 1) mod 7 ;
          if ( k = 1 ) then
          begin

⌨️ 快捷键说明

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