首页 > 其他分享 >Delphi调用Asterisk系统AMI接口取得来电号码

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

时间:2023-06-21 18:31:59浏览次数:37  
标签:AMI Lines Delphi Asterisk Add Values SLD Self

      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接口取得来电号码_Self_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接口取得来电号码_数据_03


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

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

Action:login
UserName:admin
Secret:xxxxxxxx

Delphi调用Asterisk系统AMI接口取得来电号码_Asterisk_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接口取得来电号码_数据_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接口取得来电号码_Self_06

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



标签:AMI,Lines,Delphi,Asterisk,Add,Values,SLD,Self
From: https://blog.51cto.com/u_12668715/6527982

相关文章

  • 【paramiko】基于paramiko封装SSH连接服务器执行命令
    1、官方文档paramiko·PyPIWelcometoParamiko’sdocumentation!—Paramikodocumentation 2、安装pipinstallparamiko 3、示例importparamiko#建立一个sshclient对象ssh=paramiko.SSHClient()#将信任的主机自动加入到host_allow列表,须放在connect......
  • TheRoleofSpatialPyramidalPoolinginConvolutionalNeuralNe
    目录1.引言2.技术原理及概念2.1.基本概念解释2.2.技术原理介绍2.3.相关技术比较3.实现步骤与流程3.1.准备工作:环境配置与依赖安装3.2.核心模块实现3.3.集成与测试4.示例与应用4.1.实例分析4.2.核心代码实现4.3.代码讲解说明4.4.应用场景介绍5.优化与改进5.1.性能优......
  • Python中的DYNAMIXEL快速入门指南
    原文链接:https://www.youtube.com/watch?v=LAizFTTdL8o hisvideowillbecoveringtherequiredcomponentsandhardware&softwaresetup,andfinallyruntheDYNAMIXELinPythonwithDYNAMIXELSDKwithinjustafewMINUTES. 本视频将涵盖所需的组件和硬件、软......
  • Delphi 用TDatasetToJSONBridge原生支持DataSet导出Json
    Xalion发现data.DBJson单元,不知什么时候加的,官方帮助中也没有写。procedureTForm18.Button2Click(Sender:TObject);varcV:TDatasetToJSONBridge;jo:Tjsonobject;begincV:=TDatasetToJSONBridge.Create;trycV.Dataset:=mt;jo:=Tjsonobject(cV.Pro......
  • Skia For Delphi 6.0 beta 1
    这个版本,将是与官方集成后的版本,Skia.pas都改成System.Skia了!爽!!期待Delphi12的发布! ......
  • unity将安卓streamingAssetsPath文件复制到persistentDataPath
    privatevoidTestCopy(){stringfrom=Application.streamingAssetsPath+"/Test/test.txt";stringto=Application.persistentDataPath+"/Test/";CopyFile(from,to);}publicstaticvoidCopyFile(stringsourcePath,stringdesti......
  • 微信小程序—智能小蜜(基于智能语义解析olami开放平台)
    概述该程序支持功能有查天气、查诗词、查百科、算算术、查日历、看笑话、看故事、聊天等,通过用户输入语句智能解析用户意图输出相应答案。详细一、准备工作1、电脑需要安装有微信web开发者工具,如果没有请点击这里安装:下载地址2、成为微信小程序开发者,需要用到appID,详......
  • delphi7使用rave5.0展现数据库数据报表
    时隔多年,回头再次拿起Delphi。使用Delphi7展现Rave设计的报表,尝试了很多次,目前仅掌握的两种方式:①不在delphi程序中设置数据库连接组件,直接调用Rave报表文件展现,获取数据是在rave文件中设置数据库连接并完成的(DriverDataView)。(这种还需要补充加载驱动解决程序无法执行的问题)②......
  • delphi model序列和还原
    delphimodel序列和还原封装了json和protobuf。unitserialize;///<author>cxg2022-8-30</author>interfaceusesSystem.SysUtils,Grijjy.ProtocolBuffers,System.JSON.Serializers;typeTSerial=classpublic//unmarshalclassfunctionun......
  • delphi7使用QuickReport快速生成报表
    QuickReport报表组件是Delphi7之前版本广泛使用的数据库报表设计工具组件,在Delphi7版本中默认没有加载在Delphi7的工具栏上。因此,需要手动安装加载一下,安装QReport组件插件步骤如下:①在Delphi7中执行菜单[Component]==>[InstallPackages...];②点击按钮[Add...],出现‘AddDesi......