Delphi调用Asterisk系统AMI接口取得来电号码

奋斗吧
奋斗吧
擅长邻域:未填写

标签: Delphi调用Asterisk系统AMI接口取得来电号码 博客 51CTO博客

2023-06-21 18:24:12 225浏览

Delphi调用Asterisk系统AMI接口取得来电号码,Delphi调用AsteriskAMI管理接口取得来电号码Asterisk开源呼叫中心系统调用

      Asterisk 是一个开放源代码的软件VoIP PBX系统, AMI  (Asterisk Manager Interface)。是Asterisk的管理接口。通过此接口,可以实现对Asterisk系统的监控和控制。通过调用AMI接口可以灵活的做很多事情,比如调用Asterisk系统AMI接口取得来电号码.

在调用接口前,先查看下新安装的Asterisk PBX系统AMI接口的管理配置,配置在/etc/asterisk/manager.conf

cd /etc/asterisk

cat manager.conf

Delphi调用Asterisk系统AMI接口取得来电号码_Delphi

记下需要的信息用户名,密码及端口号 ,使用vi编辑配置能调用接口的网段 permit 这个参数

在Delphi我们可以用TClientSocket控件进行连接AMI接口服务,拖一个控件到窗口上,配置组件 Address及上一步取得的端口号,这里可以尝试验证是否能连接,将Active设置为True,如果提示错误,请注意检查地址及端口号是否正确,同时注意Asterisk 所在的主机是否开启了防火墙,检查网段

Delphi调用Asterisk系统AMI接口取得来电号码_Asterisk_02

至此是能连接上AMI接口服务了,但是取不到数据,验证一下,确实如此,查资料得知,连接上后需要发送用户名及密码给AMI再次进行权限验证,才能取到数据

procedure TFormAmiMain.Btn_ServerOpenClick(Sender: TObject);
begin
  //连接AMI
  try
    Cs_AMI.Close;
    Cs_AMI.ClientType := ctNonBlocking;

    Cs_AMI.Address := AMIAddress;
    Cs_AMI.Port := AMIPort;
    Cs_AMI.Open;
    //Cs_AMI.Active := True;
  except
    on e: Exception do
    begin
      WriteMainSysLog('注意:连接AsteriskAMI失败.错误:' + E.message);
      Application.MessageBox(PChar('注意:连接AsteriskAMI失败.错误:' + E.message), '错误提示', MB_OK + MB_ICONERROR);
     // exit;
    end;
  end; 

end;

这里可以验证观察一下,确实取不到数据

Delphi调用Asterisk系统AMI接口取得来电号码_Delphi_03


下面这里是关键,这里是有一个坑需要处理的

我们需要在 TClientSocket连接上后,给Asterisk AMI接口发送用户名及密码,具体格式如下:

Action:login
UserName:admin
Secret:xxxxxxxx

Delphi调用Asterisk系统AMI接口取得来电号码_Self_04

procedure TFormAmiMain.Cs_AMIConnect(Sender: TObject;
  Socket: TCustomWinSocket);

var s: string;
begin  
  WriteMainSysLog('连接成功。');
  WriteMainSysLog('发送登陆AsteriskAMI命令...');
  s := 'Action:login' + #13#10
    + 'UserName:' + AMIUser + #13#10
    + 'Secret:' + AMIPwd + #13#10
    + #13#10;
  Cs_AMI.Socket.SendText(s);

end;

启动软件,看到有数据

Delphi调用Asterisk系统AMI接口取得来电号码_List_05

在TClientSocket组件onRead取到数据后,想取得来电号码,需要对接收到的数据进行解析

procedure TFormAmiMain.cs_AMIRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  RStr: string;
begin
  //粘包 多段数据组合的 ,需分解的
  RStr := Socket.ReceiveText;
  try
   // '***检测弹屏*************');
      //弹屏取数
     AMIReadCTIPopup(RStr);
    //self.Memo1.Lines.Add(RStr);
    //'********弹屏取数完毕*************');

   //发送数据
   //发送完毕
  except
  end;


end;

解析出来号码的过程

procedure TFormAmiMain.AMIReadCTIPopup(ReceiveText: string);
var
  Slt: TStringList;
  i, j: integer;
  s: string;
  SLD: TStringList;

begin
  Slt := TStringList.Create;

 // self.Memo1.Lines.Add('**********************');
  try
    SLD := TStringList.Create;
    try
      SLT.Text := ReceiveText;
      for i := 0 to slt.Count - 1 do
      begin
       // self.Memo1.Lines.Add(Format('%.5d', [i]) + '   ' + SLT.Strings[I]);

        s := Trim(SLT.Strings[I]);
      //前一行 'ChannelState: 6'
        if s = 'ChannelStateDesc: Up' then
        begin
      {
        self.Memo2.Lines.Add('***********************');

        self.Memo2.Lines.Add(SLT.Strings[i - 2]);
        self.Memo2.Lines.Add(SLT.Strings[i - 1]);
        self.Memo2.Lines.Add(SLT.Strings[i]);
        self.Memo2.Lines.Add(SLT.Strings[i + 1]);
        self.Memo2.Lines.Add(SLT.Strings[i + 2]);
        self.Memo2.Lines.Add(SLT.Strings[i + 3]);
        self.Memo2.Lines.Add(SLT.Strings[i + 4]);
       }
       // self.Memo2.Lines.Add('**********************');

{//样式格式
Channel=SIP/1102-000001a0
ChannelState=6
ChannelStateDesc=Up
CallerIDNum=1102
CallerIDName=device
ConnectedLineNum=1109
ConnectedLineName=1109
}

          SLD.Clear;
          SLD.Add(StringReplace(SLT.Strings[i - 3], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i - 2], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i - 1], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i + 1], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i + 2], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i + 3], ': ', '=', [rfReplaceAll, rfIgnoreCase]));
          SLD.Add(StringReplace(SLT.Strings[i + 4], ': ', '=', [rfReplaceAll, rfIgnoreCase]));

         // SELF.Memo2.Lines.Add('**************');
         //  Self.Memo2.Lines.Add(SLD.Text);
          if SLD.Values['CallerIDName'] = 'device' then
          begin
            DBLogAMIPOPUP(DMDB.ADOCon, SLD);

            //
            {
            Self.Memo2.Lines.Add('--被叫--' + SLD.Values['CallerIDNum']);
            Self.Memo2.Lines.Add('来电弹屏号码' + SLD.Values['ConnectedLineNum']);
            Self.memo2.lines.add('Timestamp Is ::' + SLD.Values['Timestamp']);
            Self.memo2.lines.add('Channel Is ::' + SLD.Values['Channel']);
            Self.memo2.lines.add('ChannelState Is ::' + SLD.Values['ChannelState']);
            Self.memo2.lines.add('ChannelStateDesc Is ::' + SLD.Values['ChannelStateDesc']);

            Self.memo2.lines.add('CallerIDNum Is ::' + SLD.Values['CallerIDNum']);
            Self.memo2.lines.add('CallerIDName Is ::' + SLD.Values['CallerIDName']);
            Self.memo2.lines.add('ConnectedLineNum Is ::' + SLD.Values['ConnectedLineNum']);
            Self.memo2.lines.add('ConnectedLineName Is ::' + SLD.Values['ConnectedLineName']);
             }
             //转发取得的号码消息给客户端
            for j := Ss_1.Socket.ActiveConnections - 1 downto 0 do
            begin
              try
                Ss_1.socket.connections[j].sendtext(SLD.Text);
      //Ss_1.Socket.Connections[j].RemoteAddress
      //WriteMainSysLog(SLD.Text);
              except
                on E: Exception do
                  WriteMainSysLog('发送弹屏信息出错,错误:' + E.Message);
              end;
            end;

          end;
           {
          else
           if SLD.Values['ConnectedLineName']= 'device' then
         // if SLD.Values['CallerIDName'] <> 'device' then
          begin
            //

            Self.Memo2.Lines.Add('--主叫--' + SLD.Values['CallerIDNum']);
            Self.Memo2.Lines.Add('呼叫号码' + SLD.Values['ConnectedLineNum']);
             Self.memo2.lines.add('Timestamp Is ::' + SLD.Values['Timestamp']);

            Self.memo2.lines.add('Channel Is ::' + SLD.Values['Channel']);
            Self.memo2.lines.add('ChannelState Is ::' + SLD.Values['ChannelState']);
            Self.memo2.lines.add('ChannelStateDesc Is ::' + SLD.Values['ChannelStateDesc']);

            Self.memo2.lines.add('CallerIDNum Is ::' + SLD.Values['CallerIDNum']);
            Self.memo2.lines.add('CallerIDName Is ::' + SLD.Values['CallerIDName']);
            Self.memo2.lines.add('ConnectedLineNum Is ::' + SLD.Values['ConnectedLineNum']);
            Self.memo2.lines.add('ConnectedLineName Is ::' + SLD.Values['ConnectedLineName']);

          end;}
         // SELF.Memo2.Lines.Add('**************');

        end;
      end;
     // self.Memo1.Lines.Add('**********************');
    finally
      SLD.Free;
    end;
  finally
    Slt.Free;
  end;
end;

解析出来电号码后,我们就可以用TServerSocket实现转发给客户端了,这种方式实时性非常高

客户端用TClientSocket接收消息

Delphi调用Asterisk系统AMI接口取得来电号码_Delphi_06

 至此我们即能调用AMI取得来电号码了,如果还想进一步用Asterisk AMI 做更多的事,需要更深入了解AMI接口命令行.



好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695