Difference between revisions of "Telephone system:autopatch"
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 | ||
}} | }} | ||
− | + | <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 [ | + | 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 === | ||
− | + | :Using Stabo freecomm 450 portable transceivers | |
+ | :[[File:autopatch_schematic.png|335px|FreeSWITCH autopatch schematic]] | ||
=== perl script === | === 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 === | === 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> | ||
+ | |||
+ | [[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 | |
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
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>