ASL to DMR Bridge...changing talkgroups


Dan K0TI
 

I'll contribute to this method of doing this. This is a combination of Steve N4IRS's script and Mike AC2VK's use of the autopatchup command to pass the talk group number. 
With it you can change to any talk group without having to set up a command before hand in rpt.conf. It also features filtering of what talk groups are available. You can refuse certain talk groups
and allow some or all others, or allow certain talk groups and refuse all others. See comments in the code on how to set this up. If you don't want it to be so verbal just comment out those speaking bits you don't like. It also has the ability to automatically key up for 1 second on the new talk group automatically which allows you to change talk groups while ASL is in monitor mode.

73 Dan K0TI

So there are 3 parts.
1. A number of stanzas in extensions.conf (put them in /etc/asterisk/custom/extensions.conf)
2. A bash/python script /usr/local/sbin/dmrtuneTG.sh.  (make this file executable with chmod +x /usr/local/sbin/dmrtuneTG.sh) 
3. Add an autopatch line in rpt.conf for the command, see example in custom/extensions.conf

Here is the extensions file: /etc/asterisk/custom/extensions.conf  (add to this file if you already have one)
>>>>>>>>> extensions.conf >>>>>>>>>>>>>
; routing for sending dmr talkgroup change command to the dvswitch stack
;
; March 2019 Dan K0TI
;
; Place this in /etc/asterisk/custom/extensions.conf
; Requires script /usr/local/sbin/dmrtuneTG.sh
;
; Calls dmrtuneTG.sh with the extenstion (talkgroup) that is dialed in.
; Auto Patch Command in rpt.conf would look like this
; 96 = autopatchup,context=dmr_tune_tg,noct=1,farenddisconnect=1,dialtime=20000,quiet=1
;
; *9631081 to would select talk group 31081 (if allowed in dmr_tune_tg1 stanza)

[dmr_tune_tg]
; Change these for your location  (DMRNODE and DNRKEY)
;
exten => _.!,1,Set(DMRNODE=200); Node number of DMR Bridge
exten => _.!,2,Set(DMRKEY=YES) ; should we key tg after set (YES/NO)
exten => _.!,3,Goto(dmr_tune_tg1|0${EXTEN}|1)
[dmr_tune_tg1]
;
; Put talkgroups here that you do NOT want allowed (examples, adjust to your needs)
; Remember you need to prefix the talkgroup number with '0'
;
exten => _0.,1,NooP(${EXTEN})
; refuse 2100 - 2199
exten => _02XXX,2,Goto(dmr_unavailable|${EXTEN}|1)
; refuse 3100 = 3199
exten => _031XX,2,Goto(dmr_unavailable|${EXTEN}|1)
; refuse TAC 310
exten => _0312,2,Goto(dmr_unavailable|${EXTEN}|1)
; refuse North America
exten => _093,2,Goto(dmr_unavailable|${EXTEN}|1)
;
; Put talkgroups here that you want to allow (or use allow all others below)
;
; Allow TAC 310-319 (312 is refused above)
exten => _031X,2,Goto(dmr_tune_tg2|${EXTEN}|1)
; Allow 31000 - 31999
exten => _031XXX,2,Goto(dmr_tune_tg2|${EXTEN}|1)
;
; if you want to refuse all others uncomment this line
;exten => _0.,2,Goto(dmr_unavailable|${EXTEN}|1)
;
; if you want to allow all others uncomment this
; if you uncomment this then other allow statemenst above are not needed.
exten => _0.,2,Goto(dmr_tune_tg2|${EXTEN}|1)
;
exten => _0.,3,Hangup()

[dmr_tune_tg2]
; now send the command to the Analog Bridge and give feedback to usr
exten => _0.,1,System(/usr/local/sbin/dmrtuneTG.sh ${EXTEN:1} ${DMRNODE} ${DMRKEY})
exten => _0.,n,Playback(connected&to&letters/d&letters/m&letters/r)
exten => _0.,n,SayDigits(${EXTEN:1})
exten => _0.,n,Hangup()

[dmr_unavailable]
; usr put in talk group number that is not allowed
exten => _0.,1,Wait(1)
exten => _0.,n,Playback(letters/d&letters/m&letters/r)
exten => _0.,n,SayDigits(${EXTEN:1})
exten => _0.,n, Playback(unavailable)
exten => _0.,n,Hangup()




>>>>>>>> dmrtuneTG.sh >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#!/bin/bash
# /*
#  * Copyright (C) 2018 N4IRR
#  *
#  * Permission to use, copy, modify, and/or distribute this software for any
#  * purpose with or without fee is hereby granted, provided that the above
#  * copyright notice and this permission notice appear in all copies.
#  *
#  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
#  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
#  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
#  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#  * PERFORMANCE OF THIS SOFTWARE.
#  */
#
#  Additions by K0TI  March 2019
#   Can be called with 3 paramters TalkGroup DMRNode YES|NO
#   If DMRNode and YES is supplied the talkgroup will be keyed up for 1 second
#   after changing. This allows use of talkgroup changes when ASL node is
#   connected in montor mode
#
###############################
# Python Function to send TalkGroup change to Analog Bridge
##
function tune() {
python - <<END
#!/usr/bin/env python
import sys
import socket
import struct
cmd = "txTg=$1".encode("utf-8")
_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cmd = struct.pack("BB", 0x05, len(cmd))[0:2] + cmd
# Set the second value below to match the rxPort in the [AMBE_AUDIO] stanza of Analog_Bridge.ini
_sock.sendto(cmd, ('127.0.0.1', 31100))
_sock.close()
END
}
##########################
#
if [[ $# == 0 || $# == 2 ]]; then
    echo ""
    echo "Usage: $0 TG [ASLNode] [YES|NO]"
    echo "  * TG:       DMR Talkgroup to select"
    echo "  * ASLNode:  ASL node number of DMR channel"
    echo "  * YES|NO:   YES or NO, determines if script keys up"
    echo "              on new talkgroup for 1 second"
    echo ""
    exit 1
fi
#
# Test for valid talkgroup ( TG > 0 && <  16776416)
if ! [[ $1 =~ ^[0-9]+$ && "$1" -gt "0" && "$1" -lt 16776416 ]] ; then
    echo "Invalid Talk Group Number"
    exit 1
fi
# now pass the new talkgroup to Analog_Bridge
echo "Changing Analog Bridge to Talk Group $1"
tune $1
# Test for node number
if [[ -z $2 ]] ; then
    # if no node number supplied just exit
    exit 1
fi
# Test for valid node number (node > 0 &&  < 1000000)
if ! [[ $2 =~ ^[0-9]+$ && "$2" -gt "0" && "$2" -lt "1000000" ]] ; then
    echo "Invalid Node Number"
    exit 1
fi
# If KEY Paramater supplied is YES keyup on talkgroup for 1 second
# Anything other than 'YES' is ignored
if  [[  "$3" == "YES" ]] ; then
    echo "Keying TG $1 on node $2 for 1 second"
    # send 1 second of silence
    /usr/sbin/asterisk -rx "rpt localplay $2 silence/1"
fi
exit

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


Tim - KX4ZU
 

Dan K0TI,
Thanks for this info.  I just got the Allstar to DMR Bridge setup and it's working great.  Very easy to change talkgroups using DTMF commands, as described above.

Take Care!
Tim
KX4ZU
AllStar node: 532520
Hamshack Hotline: x-11703


John Springman - KB3AWQ
 

When I run this script it works fine if I am on the bash shell.  When I add it in the rpt.conf to do it by dtmf, it gives me a busy signal like on the phone and i have to restart to clear it so not sure what may have happened on mine.. 


Brad N8PC
 

What script are you running and how is it configured in your rpt file?


On Sun, Nov 21, 2021, 2:43 AM John Springman - KB3AWQ via groups.io <fpcaptain=yahoo.com@groups.io> wrote:
When I run this script it works fine if I am on the bash shell.  When I add it in the rpt.conf to do it by dtmf, it gives me a busy signal like on the phone and i have to restart to clear it so not sure what may have happened on mine.. 


John Springman - KB3AWQ
 

The dmrtuneTG.sh one and the one Autopatch one below below.  I dont have a custom folder i asterisk folder though.


Steve N4IRS
 

On 11/21/21 7:31 PM, John Springman - KB3AWQ via groups.io wrote:
The dmrtuneTG.sh one and the one Autopatch one below below.  I dont have a custom folder i asterisk folder though.


John Springman - KB3AWQ
 

Some of that is sinking in to me, but the stuff posted below seems to be more understandable.  The script form below to run in the bash shell works just fine.  Directions to copy and paste this to this in this local and change this to this would be best. 

I was successful in doing a crontab -e to have it switch to a certain talkgroup at a certain time and day. 

@reboot sleep 30 && systemctl restart mmdvm_bridge ; this is just for a reboot of the pi to start mmdvn_bridge
00 20 * * 1 /usr/local/sbin/dmrtuneTG.sh 314230 1999 yes ; active TG locally switched to
#00 04 * * 0 /usr/local/sbin/dmrtuneTG.sh 31421 1999 yes ; test that is commented out for PA statewide tac 1


I pasted this at the bottom of the etc/asterisk/extentions.conf (I dont have a custom folder)
; routing for sending dmr talkgroup change command to the dvswitch stack
;
; March 2019 Dan K0TI
;
; Place this in /etc/asterisk/custom/extensions.conf
; Requires script /usr/local/sbin/dmrtuneTG.sh
;
; Calls dmrtuneTG.sh with the extenstion (talkgroup) that is dialed in.
; Auto Patch Command in rpt.conf would look like this
; 96 = autopatchup,context=dmr_tune_tg,noct=1,farenddisconnect=1,dialtime=20000,quiet=1
;
; *9631081 to would select talk group 31081 (if allowed in dmr_tune_tg1 stanza)

[dmr_tune_tg]
; Change these for your location  (DMRNODE and DNRKEY)
;
exten => _.!,1,Set(DMRNODE=200); Node number of DMR Bridge
exten => _.!,2,Set(DMRKEY=YES) ; should we key tg after set (YES/NO)
exten => _.!,3,Goto(dmr_tune_tg1|0${EXTEN}|1)
[dmr_tune_tg1]
;
; Put talkgroups here that you do NOT want allowed (examples, adjust to your needs)
; Remember you need to prefix the talkgroup number with '0'
;
exten => _0.,1,NooP(${EXTEN})
; refuse 2100 - 2199
exten => _02XXX,2,Goto(dmr_unavailable|${EXTEN}|1)
; refuse 3100 = 3199
exten => _031XX,2,Goto(dmr_unavailable|${EXTEN}|1)
; refuse TAC 310
exten => _0312,2,Goto(dmr_unavailable|${EXTEN}|1)
; refuse North America
exten => _093,2,Goto(dmr_unavailable|${EXTEN}|1)
;
; Put talkgroups here that you want to allow (or use allow all others below)
;
; Allow TAC 310-319 (312 is refused above)
exten => _031X,2,Goto(dmr_tune_tg2|${EXTEN}|1)
; Allow 31000 - 31999
exten => _031XXX,2,Goto(dmr_tune_tg2|${EXTEN}|1)
;
; if you want to refuse all others uncomment this line
;exten => _0.,2,Goto(dmr_unavailable|${EXTEN}|1)
;
; if you want to allow all others uncomment this
; if you uncomment this then other allow statemenst above are not needed.
exten => _0.,2,Goto(dmr_tune_tg2|${EXTEN}|1)
;
exten => _0.,3,Hangup()

[dmr_tune_tg2]
; now send the command to the Analog Bridge and give feedback to usr
exten => _0.,1,System(/usr/local/sbin/dmrtuneTG.sh ${EXTEN:1} ${DMRNODE} ${DMRKEY})
exten => _0.,n,Playback(connected&to&letters/d&letters/m&letters/r)
exten => _0.,n,SayDigits(${EXTEN:1})
exten => _0.,n,Hangup()

[dmr_unavailable]
; usr put in talk group number that is not allowed
exten => _0.,1,Wait(1)
exten => _0.,n,Playback(letters/d&letters/m&letters/r)
exten => _0.,n,SayDigits(${EXTEN:1})
exten => _0.,n, Playback(unavailable)
exten => _0.,n,Hangup()

The dmrtuneTG.sh file I created in /usr/local/sbin/ and I pasted this in there.  This seems to work fine.
#!/bin/bash
# /*
#  * Copyright (C) 2018 N4IRR
#  *
#  * Permission to use, copy, modify, and/or distribute this software for any
#  * purpose with or without fee is hereby granted, provided that the above
#  * copyright notice and this permission notice appear in all copies.
#  *
#  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
#  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
#  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
#  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#  * PERFORMANCE OF THIS SOFTWARE.
#  */
#
#  Additions by K0TI  March 2019
#   Can be called with 3 paramters TalkGroup DMRNode YES|NO
#   If DMRNode and YES is supplied the talkgroup will be keyed up for 1 second
#   after changing. This allows use of talkgroup changes when ASL node is
#   connected in montor mode
#
###############################
# Python Function to send TalkGroup change to Analog Bridge
##
function tune() {
python - <<END
#!/usr/bin/env python
import sys
import socket
import struct
cmd = "txTg=$1".encode("utf-8")
_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cmd = struct.pack("BB", 0x05, len(cmd))[0:2] + cmd
# Set the second value below to match the rxPort in the [AMBE_AUDIO] stanza of Analog_Bridge.ini
_sock.sendto(cmd, ('127.0.0.1', 31100))
_sock.close()
END
}
##########################
#
if [[ $# == 0 || $# == 2 ]]; then
    echo ""
    echo "Usage: $0 TG [ASLNode] [YES|NO]"
    echo "  * TG:       DMR Talkgroup to select"
    echo "  * ASLNode:  ASL node number of DMR channel"
    echo "  * YES|NO:   YES or NO, determines if script keys up"
    echo "              on new talkgroup for 1 second"
    echo ""
    exit 1
fi
#
# Test for valid talkgroup ( TG > 0 && <  16776416)
if ! [[ $1 =~ ^[0-9]+$ && "$1" -gt "0" && "$1" -lt 16776416 ]] ; then
    echo "Invalid Talk Group Number"
    exit 1
fi
# now pass the new talkgroup to Analog_Bridge
echo "Changing Analog Bridge to Talk Group $1"
tune $1
# Test for node number
if [[ -z $2 ]] ; then
    # if no node number supplied just exit
    exit 1
fi
# Test for valid node number (node > 0 &&  < 1000000)
if ! [[ $2 =~ ^[0-9]+$ && "$2" -gt "0" && "$2" -lt "1000000" ]] ; then
    echo "Invalid Node Number"
    exit 1
fi
# If KEY Paramater supplied is YES keyup on talkgroup for 1 second
# Anything other than 'YES' is ignored
if  [[  "$3" == "YES" ]] ; then
    echo "Keying TG $1 on node $2 for 1 second"
    # send 1 second of silence
    /usr/sbin/asterisk -rx "rpt localplay $2 silence/1"
fi
exit

In the rpt.conf file under the functions stanza I put this
96 = autopatchup,context=dmr_tune_tg,noct=1,farenddisconnect=1,dialtime=20000,quiet=1 

I then entered *9631421 to test it on our state tac channel and only got a busy phone continuous tone. 
---------------------
Seeing this in the link sent
; DMR = cmd, /opt/MMDVM_Bridge/dvswitch.sh mode DMR
What does this do and where is it to be put?  Also there is no dvswitch,sh in that folder.  I can add one but need the script to paste in.

What is this -
75 = cmd, /tmp/ssz.sh one two three


Where does this get put -

; context = tgtune               : Override default context with "tgtune"

; dialtime = 90000               : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second)

; farenddisconnect = 1        :   Automatically disconnect when called party hangs up

; noct = 1                             :  Don't send repeater courtesy tone during autopatch calls

; quiet = 1                            :  Don't send dial tone, or conne

 

; Here is the dialplan that will be executed by the above

 

; [tgtune]

; exten = _X.,1,Wait,1

; exten = _X.,n,SayAlpha(dmr,${EXTEN}) ; Say "d m r 3100"

; exten = _X.,n,Wait,3  ; this gives you a chance (3sec) to cancel by hitting the '#' key if incorrect.

; exten = _X.,n,System(/opt/Analog_Bridge/dvswitch.sh tune ${EXTEN}) ; run the script tgtune.sh what a paramater of 3100

; exten = _X.,n,Hangup ; Done, return to normal operation


Not sure what this is or where this gets put -

; dvswitch-demo*CLI> rpt fun 1999 *77

; [Feb  1 13:46:29] NOTICE[536]: app_rpt.c:4084 function_cmd: cmd param =  /tmp/ssz.sh one two three, digitbuf =

 

; root@dvswitch-demo:/tmp# cat out.txt

; /tmp/ssz.sh one two three

; one two three