Difference between revisions of "Telephone system:autopatch"

From Hackerspace ACKspace
Jump to: navigation, search
m (added category)
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
{{Project
 
{{Project
 +
|Featured=No
 
|State=Completed
 
|State=Completed
 
|Members=xopr
 
|Members=xopr
 
|Description=use a VoIP system to communicate over radio
 
|Description=use a VoIP system to communicate over radio
 +
|Picture=autopatch.jpg
 
}}
 
}}
[[File:autopatch.jpg|335px|thumb|right|FreeSWITCH autopatch using Stabo freecomm 450 portable transceivers]]
+
<onlyinclude>To connect the <abbr title="private automated branch exchange">PABX</abbr> to an external communications channel, one needs a tiny bit of hardware and some scripting to get it working.
 +
A proof of concept is made that used the <abbr title="private mobile radio">PMRs</abbr> in the space and a couple of components on a perf-board.
 +
</onlyinclude>
  
 
== synopsis ==
 
== synopsis ==
Inspired by [http://wiki.freeswitch.org/wiki/Examples_Ham_Radio freeswitch.org's Examples Ham Radio], I wanted to be able to communicate over the air using FreeSWITCH.
+
Inspired by [https://freeswitch.org/confluence/display/FREESWITCH/Ham+Radio freeswitch.org's Examples Ham Radio], I wanted to be able to communicate over the air using FreeSWITCH.
  
 
It's a simple script with the least amount of hardware you can think of.
 
It's a simple script with the least amount of hardware you can think of.
Line 13: Line 17:
 
== implementation ==
 
== implementation ==
 
=== hardware ===
 
=== hardware ===
todo
+
:Using Stabo freecomm 450 portable transceivers
 +
:[[File:autopatch_schematic.png|335px|FreeSWITCH autopatch schematic]]
  
 
=== perl script ===
 
=== perl script ===
todo
+
#!/usr/bin/perl
 +
 +
use strict;
 +
use Switch;
 +
use Data::Dumper;
 +
use POSIX qw(strftime);
 +
use Device::SerialPins;
 +
 +
my $conference_name = 'radio';
 +
my $roger_beep      = 'tone_stream://%(60,0,2000);%(60,0,1200);%(60,0,800);% (80,0,1500)';
 +
my $serial_port    = '/dev/ttyUSB0';
 +
 +
our $session;
 +
 +
my $ptt_port        = new Device::SerialPins( $serial_port );
 +
my $api            = new freeswitch::API;
 +
my $con            = new freeswitch::EventConsumer( 'CUSTOM' ); #all
 +
my $nTalkers        = 0;
 +
 +
resetTransmission();
 +
 +
freeswitch::consoleLog( 'INFO', "Registered on CUSTOM events\n" );
 +
 +
while( $session->ready )
 +
{
 +
  # Check every half a second to prevent a small cpu from clipping
 +
  #sleep( 0.5 ); # eats cpu
 +
  $session->sleep( 500 );
 +
 +
  my $event = $con->pop;
 +
 +
  if ( $event
 +
    && ($event->getHeader('Event-Name') eq 'CUSTOM' )
 +
    && ( $event->getHeader('Event-Subclass') eq 'conference::maintenance' ))
 +
  {
 +
    my $action = $event->getHeader('Action');
 +
 +
    if ( $event->getHeader('Caller-Channel-Name') =~ m/^portaudio/ )
 +
    {
 +
      # portaudio event, check DTMF
 +
      if( $action eq 'dtmf' )
 +
      {
 +
        my $dtmf_key = $event->getHeader('dtmf-key');
 +
        freeswitch::consoleLog('INFO', 'DTMF: ' . $dtmf_key );
 +
        switch( $dtmf_key )
 +
        {
 +
        }
 +
      }
 +
    }
 +
    else
 +
    {
 +
      # event from other member
 +
      switch ( $action )
 +
      {
 +
        case 'start-talking'
 +
        {
 +
          PTT( 1 );
 +
        }
 +
        case 'stop-talking'
 +
        {
 +
          PTT( 0 );
 +
        }
 +
        case m/^(del|mute|deaf)-member$/
 +
        {
 +
          # recount the number of talkers since the person throwing the horn
 +
          # onhook might trigger a talk event before leaving
 +
          handleTalkerCount();
 +
        }
 +
      }
 +
    }
 +
  }
 +
 +
  # if we have 2 members left (portaudio and this script), hup all members and stop the conference
 +
}
 +
 +
sub PTT
 +
{
 +
  if ( shift )
 +
  {
 +
    # New talker
 +
    $nTalkers++;
 +
    if ( $nTalkers == 1 )
 +
    {
 +
      freeswitch::consoleLog('INFO', "Start of transmission\n" );
 +
      $ptt_port->set_rts( 1 );
 +
    }
 +
  } else {
 +
    # Talker done
 +
    $nTalkers--;
 +
 +
    if ( $nTalkers == 0 )
 +
    {
 +
      resetTransmission();
 +
    }
 +
  }
 +
 +
  # resetTransmission could change the number of talkers
 +
  if ( $nTalkers < 0 )
 +
  {
 +
    freeswitch::consoleLog('WARNING', "Number of talkers was below zero, resetting..\n" );
 +
    $nTalkers = 0;
 +
  }
 +
}
 +
 +
sub resetTransmission
 +
{
 +
  # reset the number of talkers
 +
  $nTalkers = 0;
 +
 +
  # roger beep
 +
  $api->execute( 'conference', $conference_name.' play '.$roger_beep );
 +
  $session->sleep( 500 );
 +
  #sleep( 0.7 ); # eats cpu
 +
 +
  # end of transmit
 +
  $ptt_port->set_rts( 0 );
 +
 +
  freeswitch::consoleLog('INFO', "End of transmission\n" );
 +
}
 +
 +
sub handleTalkerCount
 +
{
 +
  freeswitch::consoleLog('INFO', "Member event, counting number of talkers..\n" );
 +
 +
  my $conference_info = $api->execute( 'conference', $conference_name.' list' );
 +
  my $nRealTalkers =()= $conference_info =~ /[;\|]talking[;\|]/gi;
 +
  my $nMembers = ($conference_info =~ tr/\n//);
 +
 +
  # adjust number of talkers
 +
  if ( $nRealTalkers < $nTalkers )
 +
  {
 +
    $nTalkers = $nRealTalkers + 1;
 +
    PTT( 0 );
 +
  }
 +
 +
  if ( $nMembers <= 2 )
 +
  {
 +
    freeswitch::consoleLog('INFO', "No humans in the conference anymore, terminating script..\n" );
 +
    $session->hangup();
 +
  }
 +
}
 +
 +
1; # Return value
 +
 
  
 
=== dial plan ===
 
=== dial plan ===
todo
+
The dialplan consists of two extensions: a conference where phones can dial into (1310), and an extension which runs the perl script.
 +
The conference requires a minimum of two participants. When the first person calls, the conference will automatically call the script extension and portaudio device which will be bridged directly (auto answer).
 +
 
 +
<extension name="test porto">
 +
  <condition field="destination_number" expression="^1310$">
 +
    <action application="answer"/>
 +
    <action application="conference_set_auto_outcall" data="portaudio/auto_answer"/>
 +
    <action application="conference_set_auto_outcall" data="loopback/1311"/>
 +
    <action application="conference" data="radio@ultrawideband+flags{mintwo}"/>
 +
  </condition>
 +
</extension>
 +
 +
<extension name="test porto event">
 +
  <condition field="destination_number" expression="^1311$">
 +
    <action application="answer"/>
 +
    <action application="perl" data="autopatch.pl"/>
 +
  </condition>
 +
</extension>
 +
 
 +
[[Category:Telephony]][[Category:Telephone snippet]][[Category:FreeSWITCH]]

Latest revision as of 09:20, 14 February 2018

Project: Telephone system:autopatch
Featured: No
State Completed
Members xopr
GitHub No GitHub project defined. Add your project here.
Description use a VoIP system to communicate over radio
Picture
Autopatch.jpg

To connect the PABX to an external communications channel, one needs a tiny bit of hardware and some scripting to get it working. A proof of concept is made that used the PMRs in the space and a couple of components on a perf-board.


synopsis

Inspired by freeswitch.org's Examples Ham Radio, I wanted to be able to communicate over the air using FreeSWITCH.

It's a simple script with the least amount of hardware you can think of.

implementation

hardware

Using Stabo freecomm 450 portable transceivers
FreeSWITCH autopatch schematic

perl script

#!/usr/bin/perl

use strict;
use Switch;
use Data::Dumper;
use POSIX qw(strftime);
use Device::SerialPins;

my $conference_name = 'radio';
my $roger_beep      = 'tone_stream://%(60,0,2000);%(60,0,1200);%(60,0,800);% (80,0,1500)';
my $serial_port     = '/dev/ttyUSB0';

our $session;

my $ptt_port        = new Device::SerialPins( $serial_port );
my $api             = new freeswitch::API;
my $con             = new freeswitch::EventConsumer( 'CUSTOM' ); #all
my $nTalkers        = 0;

resetTransmission();

freeswitch::consoleLog( 'INFO', "Registered on CUSTOM events\n" );

while( $session->ready )
{
  # Check every half a second to prevent a small cpu from clipping
  #sleep( 0.5 ); # eats cpu
  $session->sleep( 500 );

  my $event = $con->pop;

  if ( $event
   && ($event->getHeader('Event-Name') eq 'CUSTOM' )
   && ( $event->getHeader('Event-Subclass') eq 'conference::maintenance' ))
  {
    my $action = $event->getHeader('Action');

    if ( $event->getHeader('Caller-Channel-Name') =~ m/^portaudio/ )
    {
      # portaudio event, check DTMF
      if( $action eq 'dtmf' )
      {
        my $dtmf_key = $event->getHeader('dtmf-key');
        freeswitch::consoleLog('INFO', 'DTMF: ' . $dtmf_key );
        switch( $dtmf_key )
        {
        }
      }
    }
    else
    {
      # event from other member
      switch ( $action )
      {
        case 'start-talking'
        {
          PTT( 1 );
        }
        case 'stop-talking'
        {
          PTT( 0 );
        }
        case m/^(del|mute|deaf)-member$/
        {
          # recount the number of talkers since the person throwing the horn
          # onhook might trigger a talk event before leaving
          handleTalkerCount();
        }
      }
    }
  }

  # if we have 2 members left (portaudio and this script), hup all members and stop the conference
}

sub PTT
{
  if ( shift )
  {
    # New talker
    $nTalkers++;
    if ( $nTalkers == 1 )
    {
      freeswitch::consoleLog('INFO', "Start of transmission\n" );
      $ptt_port->set_rts( 1 );
    } 
  } else {
    # Talker done
    $nTalkers--;

    if ( $nTalkers == 0 )
    {
      resetTransmission();
    }
  }

  # resetTransmission could change the number of talkers
  if ( $nTalkers < 0 )
  {
    freeswitch::consoleLog('WARNING', "Number of talkers was below zero, resetting..\n" );
    $nTalkers = 0;
  }
}

sub resetTransmission
{
  # reset the number of talkers
  $nTalkers = 0;

  # roger beep
  $api->execute( 'conference', $conference_name.' play '.$roger_beep );
  $session->sleep( 500 );
  #sleep( 0.7 ); # eats cpu

  # end of transmit
  $ptt_port->set_rts( 0 );

  freeswitch::consoleLog('INFO', "End of transmission\n" );
}

sub handleTalkerCount
{
  freeswitch::consoleLog('INFO', "Member event, counting number of talkers..\n" );

  my $conference_info = $api->execute( 'conference', $conference_name.' list' );
  my $nRealTalkers =()= $conference_info =~ /[;\|]talking[;\|]/gi;
  my $nMembers = ($conference_info =~ tr/\n//);

  # adjust number of talkers
  if ( $nRealTalkers < $nTalkers )
  {
    $nTalkers = $nRealTalkers + 1;
    PTT( 0 );
  }

  if ( $nMembers <= 2 )
  {
    freeswitch::consoleLog('INFO', "No humans in the conference anymore, terminating script..\n" );
    $session->hangup();
  }
}

1; # Return value


dial plan

The dialplan consists of two extensions: a conference where phones can dial into (1310), and an extension which runs the perl script. The conference requires a minimum of two participants. When the first person calls, the conference will automatically call the script extension and portaudio device which will be bridged directly (auto answer).

<extension name="test porto">
  <condition field="destination_number" expression="^1310$">
    <action application="answer"/>
    <action application="conference_set_auto_outcall" data="portaudio/auto_answer"/>
    <action application="conference_set_auto_outcall" data="loopback/1311"/>
    <action application="conference" data="radio@ultrawideband+flags{mintwo}"/>
  </condition>
</extension>

<extension name="test porto event">
  <condition field="destination_number" expression="^1311$">
    <action application="answer"/>
    <action application="perl" data="autopatch.pl"/>
  </condition>
</extension>