Perl 如何使用带mod_会议的freeswitch进行按键通话、对讲机(PTT)

Perl 如何使用带mod_会议的freeswitch进行按键通话、对讲机(PTT),perl,perl-module,freeswitch,Perl,Perl Module,Freeswitch,我试着推它说话。 安卓sip客户端和服务器sip(freeswitch) 我的mod_会议有: 文件conf.xml <group name="radio"> <control action="mute" digits="0"/> <control action="deaf mute" digits="*"/> <control action="energy up" digits="9"/>

我试着推它说话。 安卓sip客户端和服务器sip(freeswitch) 我的mod_会议有:

文件conf.xml

    <group name="radio">
      <control action="mute" digits="0"/>
      <control action="deaf mute" digits="*"/>
      <control action="energy up" digits="9"/>
      <control action="energy equ" digits="8"/>
      <control action="energy dn" digits="7"/>
      <control action="vol talk up" digits="3"/>
      <control action="vol talk zero" digits="2"/>
      <control action="vol talk dn" digits="1"/>
      <control action="vol listen up" digits="6"/>
      <control action="vol listen zero" digits="5"/>
      <control action="vol listen dn" digits="4"/>
      <control action="hangup" digits="#"/>
    </group>

profile

    <profile name="radio">
     <param name="caller-controls" value="radio"/>
    </profile>

my dialplan

    <include>
     <extension name="radio_conference">
     <condition field="destination_number" expression="^1337$"/>
     <condition field="source" expression="mod_portaudio" break="never">
      <action application="perl" data="$${script_dir}/radio.pl"/>
      <action application="answer"/>
      <action application="sleep" data="1000"/>
      <action application="start_dtmf"/>
      </condition>
      <condition>
      <action application="conference" data="radio@radio"/>
      </condition>
     </extension>
    </include>

轮廓
我的拨号计划
我的脚本radio.pl

    use Device::SerialPins;
    use Getopt::Std;
    use strict;
    use FreeSWITCH::Client;
    use POSIX ':signal_h'; # used for alarm to ensure we get heartbeats
    use Switch;
    use Data::Dumper; # used to print out myhash debug info
    use File::stat;


    my $password = "1234";    # event socket password
    my $host     = "192.168.100.228";  # event socket host
    my $port     = 8021;         # event socket port
    my $device   = undef;        # radio control device (/dev/ttyS0, COM1,       etc)
    my $baud     = 9600;         # radio control device baud rate
    my $timeout  = 30;           # seconds to expect a heartbeat or        reconnect
    my $courtesy_tone = "tone_stream://%(150,150,500);%(150,0,400)"; # tone played before releasing PTT
    my $confname = "radio";      # the name of the conference
    my $extension = "1337";      # this is the extension that portaudio will call to join
    my $callsign = undef;        # disable callsign autoID - set to your callsign
    my $callsign_interval = 600; # 10 minute intervals


# for TTS anouncements played after CWID - undef to disable
    my $voice = "Allison";
    my $swift = "/opt/swift/bin/swift";
    my $filetime = 0;


# normal users do not need to edit anything below here
    my %options;
    my $fs;
    my $lastheartbeat;
    my $lastcallsign;
    my $lasttx;
    my $releasePTT=0;
    my $ptt_port;



    sub pressPTT()
    {
     $ptt_port->set_rts(1);
    }

    sub releasePTT()
    {
     $ptt_port->set_rts(0);
    }


# this connects to the event socket
    sub es_connect()
    {
     print "Connecting to $host:$port\n";
     eval {
        $fs = init FreeSWITCH::Client {-password => $password, -host =>   $host, -port => $port};
        if(defined $fs) {
            $fs->sendmsg({'command' => 'event plain heartbeat CUSTOM conference::maintenance'});
            $lastheartbeat = time;
        }
     } or do {
         print "Error connecting - waiting for retry\n";
         sleep(10);
     }
     }


     sigaction SIGALRM, new POSIX::SigAction sub {
      if ($lastheartbeat < (time - $timeout)) {
        print "Did not receive a heartbeat in the specified timeout\n";
        if (defined $fs) {
            $fs->disconnect();
            undef $fs;
        }
        es_connect();
     }

     if(defined $callsign && $lastcallsign < (time - $callsign_interval) && $lasttx > $lastcallsign) {
         pressPTT();
         $fs->command("jsapi morse.js conference radio ".$callsign);
        $lastcallsign = time;
        $releasePTT++;


        if (-f "announcement.txt") {
            if(stat("announcement.txt")->mtime > $filetime && defined     $voice $$ defined $swift) {
                system("$swift -p audio/deadair=2000,audio/sampling-   rate=8000,audio/channels=1,audio/encoding=pcm16,audio/output-format=raw -o   /tmp/announcement.raw -f announcement.txt -n $voice");
                  $fs->command("conference ".$confname." play   /tmp/announcement.raw");
            }
        }
       }

    # reset the alarm
       alarm $timeout;
     } or die "Error setting SIGALRM handler: $!\n";

     sub usage()
     {
      print "Usage: $0 [-p pass] [-P port] [-H host] [-d device] [-b    baud]\n";
     print "example: $0 -p password -P 8021 -H localhost -d /dev/ttyS0 -b     38400\n";
    exit;
     }


     sub checkArgs()
      {
       getopts("p:P:H:d:b:h",\%options);
       usage() if defined $options{h};
       $password = $options{p} if defined $options{p};
       $host = $options{H} if defined $options{H};
       $port = $options{P} if defined $options{P};
       $device = $options{d} if defined $options{d};
       $baud = $options{b} if defined $options{b};

      if(! defined $device || ! defined $password ||
       ! defined $host || ! defined $port) {
        usage();
        exit;
      }
      }


      checkArgs();
       $ptt_port = Device::SerialPins->new($device);
       releasePTT();
       es_connect();
       alarm $timeout;



       $SIG{INT} = "byebye";        # traps keyboard interrupt (^C)

      sub byebye {
       if(defined $fs) {
        $fs->command("pa hangup");
       }
       exit();
      }


      if(defined $fs) {
      $fs->command("pa call ".$extension);
      } else {
      print "Unable to start portaudio channel\n";
      }

      $lastcallsign = time;

     while (1) {
     if(defined $fs) {
        my $reply = $fs->readhash(undef);
        if ($reply->{socketerror}) {
            es_connect();
        }

        if($reply->{body}) {
            my $myhash = $reply->{event};

            if ($myhash->{'event-name'} eq "HEARTBEAT") {
                $lastheartbeat = time;
            } elsif ($myhash->{'event-subclass'} eq  "conference::maintenance") {
                if($myhash->{'conference-name'} eq $confname) {
                    if($myhash->{'caller-channel-name'} =~ m/^portaudio/)      {
                        # this is from the radio
                        if($myhash->{'action'} eq 'dtmf') {
                            switch($myhash->{'dtmf-key'}) {
                                # I will be adding some "dial"     instructions for autopatch
                                # and maybe some other settings here
                            }
                        }
                    } else {
                        # this is from everyone else
                        if ($myhash->{'action'} eq 'start-talking') {
                            print "The port is talking! keying mic\n";
                            $lasttx = time;
                            pressPTT();
                        } elsif ($myhash->{'action'} eq 'stop-talking') {
                            print "The port stopped talking! releasing    mic\n";
                            if(defined $courtesy_tone) {
                                $fs->command("conference ".$confname."   play ".$courtesy_tone);
                                $releasePTT++;
                            }
                        }
                    }

                    if($myhash->{'action'} eq 'dtmf') {
                        print "conf: $myhash->{'conference-name'}\tmember:     $myhash->{'member-id'}\tDTMF: $myhash->{'dtmf-key'}\n";
                    } elsif ($myhash->{'action'} eq 'play-file') {
                        print "conf: $myhash->{'conference-name'}\taction:    $myhash->{'action'}\tfile: $myhash->{'file'}\n";
                    } elsif ($myhash->{'action'} eq 'play-file-done') {
                        print "conf: $myhash->{'conference-name'}\taction:    $myhash->{'action'}\tfile: $myhash->{'file'}\n";
                        if($releasePTT>0) {
                            $releasePTT--;
                        }
     print "release PTT: $releasePTT\n";
                         if($releasePTT==0) {
                            releasePTT();
                        }
                    } else {
                        print "conf: $myhash->{'conference-name'}\tmemid:      $myhash->{'member-id'}\taction: $myhash->{'action'}\tCLID: $myhash->       {'caller-caller-id-number'}\n";
                    }
                } else {
                    print "conf: $myhash->{'conference-name'}\tmemid:      $myhash->{'member-id'}\taction: $myhash->{'action'}\tCLID: $myhash->       {'caller-caller-id-number'}\n";
                }
            } else {
                print Dumper $myhash;
             }
         }
      } else {
        es_connect();
       }
      }
使用Device::SerialPins;
使用Getopt::Std;
严格使用;
使用FreeSWITCH::Client;
使用POSIX':signal_h';#用于报警,以确保我们获得心跳
使用开关;
使用数据::转储程序;#用于打印myhash调试信息
使用File::stat;
我的$password=“1234”#事件套接字密码
我的$host=“192.168.100.228”#事件套接字主机
我的$port=8021;#事件套接字端口
我的$device=undef;#无线电控制装置(/dev/ttyS0、COM1等)
我的$baud=9600;#无线电控制设备波特率
我的$timeout=30;#等待心跳或重新连接的秒数
我的$credition_tone=“tone_stream://%(150150500);%(150,0400);#释放PTT前播放的音调
我的$confname=“收音机”#会议名称
我的$extension=“1337”#这是portaudio将调用以加入的扩展
我的$callsign=undef;#禁用呼号自动识别-设置为您的呼号
我的$callsign_间隔=600;#每隔10分钟
#对于在CWID-undef之后播放的TTS,禁用
我的$voice=“Allison”;
my$swift=“/opt/swift/bin/swift”;
my$filetime=0;
#普通用户不需要在此处编辑下面的任何内容
我的%选择;
我的$fs;
我的心跳;
我的$last呼号;
我的$lasttx;
我的$releasePTT=0;
我的$ptt_端口;
分按
{
$ptt\U端口->设置\U rts(1);
}
子版本PTT()
{
$ptt\U端口->设置\U rts(0);
}
#这将连接到事件套接字
子es_connect()
{
打印“连接到$host:$port\n”;
评估{
$fs=init FreeSWITCH::客户端{-password=>$password,-host=>$host,-port=>$port};
如果(定义为$fs){
$fs->sendmsg({'command'=>'event plain heartbeat CUSTOM conference::maintenance'});
$lastheartbeat=时间;
}
}或者{
打印“连接错误-等待重试\n”;
睡眠(10);
}
}
sigaction SIGALRM,新POSIX::sigaction sub{
如果($lastheartbeat<(时间-$timeout)){
打印“在指定的超时时间内没有接收到心跳信号\n”;
如果(定义为$fs){
$fs->disconnect();
undef$fs;
}
es_connect();
}
if(定义的$callsign&&$lastcallsign<(时间-$callsign\u间隔)&&$lasttx>$lastcallsign){
按ptt();
$fs->command(“jsapi morse.js会议无线电”。$callsign);
$lastcallsign=时间;
$releasePTT++;
如果(-f“announcement.txt”){
if(stat(“announcement.txt”)->mtime>$filetime&&defined$voice$$defined$swift){
系统($swift-p audio/deadair=2000,audio/sampling-rate=8000,audio/channels=1,audio/encoding=pcm16,audio/output format=raw-o/tmp/announcement.raw-f announcement.txt-n$voice);
$fs->command(“conference”$confname.play/tmp/announcement.raw”);
}
}
}
#重置警报
报警$超时;
}或“设置SIGALRM处理程序时出错:$!\n”;
子用法()
{
打印“用法:$0[-p通过]-[p端口]-[H主机]-[d设备]-[b波特率]\n”;
打印“示例:$0-p password-p8021-hlocalhost-d/dev/ttyS0-b38400\n”;
出口
}
子checkArgs()
{
getopts(“p:p:H:d:b:H”,\%options);
用法()如果定义了$options{h};
$password=$options{p}如果定义了$options{p};
$host=$options{H}(如果定义了$options{H});
$port=$options{P}如果定义了$options{P};
$device=$options{d}如果定义了$options{d};
$baud=$options{b}(如果定义为$options{b});
如果(!defined$device | |!defined$password)||
!已定义的$host | |!已定义的$port){
用法();
出口
}
}
checkArgs();
$ptt_port=Device::SerialPins->new($Device);
释放ptt();
es_connect();
报警$超时;
$SIG{INT}=“byebye”#陷阱键盘中断(^C)
sub byebye{
如果(定义为$fs){
$fs->命令(“pa挂断”);
}
退出();
}
如果(定义为$fs){
$fs->command(“pa调用”。$extension);
}否则{
打印“无法启动portaudio频道\n”;
}
$lastcallsign=时间;
而(1){
如果(定义为$fs){
my$reply=$fs->readhash(未定义);
如果($reply->{socketerror}){
es_connect();
}
如果($reply->{body}){
my$myhash=$reply->{event};
if($myhash->{'event-name'}eq“HEARTBEAT”){
$lastheartbeat=时间;
}elsif($myhash->{'event-subclass'}eq“conference::maintenance”){
if($myhash->{'conference-name'}eq$confname){
if($myhash->{'caller-channel-name'}=~m/^portaudio/){
#这是收音机里的
if($myhash->{'action'}eq'dtmf'){
开关($myhash->{'dtmf-key'}){
#我将添加一些“拨号”指示自动批处理
#也许这里还有其他一些设置
}
}
}否则{
#这是其他人的
如果($myhash->{'action'}eq'start talk'){
打印“端口正在讲话!键入麦克风\n”;
$lastt