DTMFKey and/or MDC for PTT-ID (bug?)

I help manage a fairly large network of repeaters, and on prior builds of ASL we've had good luck implementing PTTID tables in the form of the [dtmfkeys] stanza and an MDC map to fight off some of our more regressive problem children.

My understanding is that support for MDC is currently not available in ASL3, ok, however when I'm enabling dmtfkey it seems to accept any number to unlock the repeater and ignores the [dtmfkeys] list which of course defeats the purpose. Is this a known issue or is there more configuration that's needed since the prior ASL1/ASL2 builds?

Any plans to re-include MDC in the basic build? We've unfortunately got trolls starting to creep back into the network since upgrading to ASL3.

First off, let me start off with "I don't know anything about MDC" :slight_smile:

In addition, I wasn't around during the early ASL3 development but from what I've seen we did not remove functionality. Looking at the sources, I do see references to a an [enable/disable] dtmfkey variable, I see a dtmfkeys variable, and there are a bunch of "MDC" files.

If you had a working ASL2 configuration then I suspect that you can copy the relevant pieces of the configuration to ASL3 and make it work.

If you need help, and you are willing to point us to [old] documentation and willing to explain how things used to work, the reach out.

Sounds good - appreciate the comeback; essentially what we're trying to get working is some sort of PTTID authentication scheme.

So DTMFKey and the MDC mapping are not well documented, even in the old version of asterisk, but essentially you could add "dtmfkey=yes" as a string to the node configuration, and it would require a DTMF code be dialed before the repeater would accept a keyup. The codes were managed in a stanza under [dtmfkeys] which would list the number and corresponding callsign, each permitted user is assigned a code which they would program into their radio to dial out at the start of every keyup, thus automating the authorized keyup process. The stanza would be set up as follows:

[dtmfkeys]

1234=K6DSA
2341=N7WSS
3412=K7VLL

For users with commercial radios; MDC was the preferred method to authenticate - it's much quicker and more robust than DTMF in terms of decode and makes the use of this system pretty much transparent to the end user. MDC is a brief data burst that's sent out and supported by many commercial radios; it's the "squawk" you hear at the beginning of many public safety type of radios. On ASL1 and ASL2 - MDC traffic would automatically be decoded, if someone had it configured on a radio you'd see the status or identity code come across on the terminal if you're logged into the console.

While PTTID is not directly managed by the MDC side of ASL, with it decoding you could tell ASL to map DTMF codes to MDC identiy or status codes as follows, thus achiving the same result by referring to the DTMF codes above in another stanza as follows:

[mdcmacro]

I1234=K1234
I2341=K2341
I3421=K3421

The I prefix is the identity code from MDC, and the K prefix tells allstarlink to refer to a "Key" in the DTMFKeys stanza. This worked really well as we had a script set up to automatically generate a pttid.conf file that gets referenced by rpt.conf, it automatically took care of the user table with ID numbers on our website, which the Allstar server would pull in nightly and reload into the app_rpt module; a new member on the website would automatically be added to the system which saves administration headaches.

The closest to documentation available is available here; this was enough to let us get things up and running pretty easily last last time: Using MDC1200 as Telemetry?

The behavior I'm seeing with ASL3 is as follows, which is making any sort of PTTID scheme ineffective:

  • MDC no longer decodes or is enabled.
  • DTMFKey is still active, however it will take random number combinations and permit the repeater to be keyed up, more or less ignoring the DTMFKeys stanza (IE I can dial some zeros or other numbers and it'll key up, even though that code is not on the list)
1 Like

In the asterisk CLI, it looks like core set debug 2 app_rpt.so will add some additional logging.

Also, would you be OK sharing (attaching) the rpt.conf file you are using to test the MDC and/or dtmfkey behavior?

Alrighty so I was mistaken before; MDC does appear to be working. I've attached our RPT.conf file below:

;*********************************************
;********   Template-tized rpt.conf   ********
;*********************************************
; Note to editors: set tabs to 4 space characters. No wrap to keep comments neat.
; vim: tabstop=4
;
; Radio Repeater configuration file for use with app_rpt ASL3
;

[general]
node_lookup_method = file           ;method used to lookup nodes
                                    ;both = dns lookup first, followed by external file (default)
                                    ;dns = dns lookup only
                                    ;file = external file lookup only

[nodes]
401 = radio@127.0.0.1/401,NONE ; Pinal
402 = radio@127.0.0.1/402,NONE ; Lemmon
403 = radio@127.0.0.1/403,NONE ; Heliograph
404 = radio@127.0.0.1/404,NONE ; Guthrie
405 = radio@127.0.0.1/405,NONE ; Alpine
406 = radio@127.0.0.1/406,NONE ; Nutrioso

410 = radio@127.0.0.1/410,NONE ; Greens Remote Base

451 = radio@127.0.0.1/451,NONE ; Mule Mountain
452 = radio@127.0.0.1/452,NONE ; Sunsites
; 453 = radio@127.0.0.1/453,NONE ; Portal Sierra Vista
454 = radio@127.0.0.1/454,NONE ; NW Tucson

[node-main](!)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; Template for all your nodes ;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set the defaults for your node(s) here.
; Add your nodes below the line that says
; Add you nodes below.

rxchannel = dahdi/pseudo            ; No radio (hub)
node_lookup_method=file             ; Private system
extnodefile=/tmp/rpt_extnodes       ; Use private node list
duplex = 3                          ; 0 = Half duplex with no telemetry tones or hang time.
linktolink = no                     ; disables forcing physical half-duplex operation of main repeater while
linkmongain = -22                   ; Link Monitor Gain adjusts the audio level of monitored nodes when a signal from another node or the local receiver is received.
erxgain = -3                        ; Echolink receive gain adjustment
etxgain = 3                         ; Echolink transmit gain adjustment
controlstates = controlstates       ; system control state stanza
scheduler = schedule                ; scheduler stanza
functions = functions               ; Repeater Function stanza
phone_functions = functions         ; Phone Function stanza
link_functions = functions          ; Link Function stanza
telemetry = telemetry               ; Telemetry stanza
morse = morse                       ; Morse stanza
macro = macro101		    ; Default is AZ Main hub macros
wait_times = wait-times             ; Wait times stanza
context = radio                     ; dialing context for phone
callerid = "Repeater" <0000000000>  ; callerid for phone calls
accountcode = RADIO                 ; account code (optional)
hangtime = 2000                     ; squelch tail hang time (in ms) (optional, default 5 seconds, 5000 ms)
althangtime = 4000                  ; longer squelch tail
totime = 180000                     ; transmit time-out time (in ms) (optional, default 3 minutes 180000 ms)
idrecording = |iK6DSA               ; id recording or morse string
idtime = 540000                     ; id interval time (in ms) (optional) Default 5 minutes (300000 ms)
politeid = 30000                    ; time in milliseconds before ID timer expires to try and ID in the tail. (optional, default 30000)
; unlinkedct = ct4                    ; Send a this courtesy tone when the user unkeys if the node is not connected to any other nodes. (optional, default is none)
remotect = ct3                      ; remote linked courtesy tone (indicates a remote is in the list of links)
linkunkeyct = ct8                   ; sent when a transmission received over the link unkeys

lnkactenable = 1                    ; Set to 1 to enable the link activity timer. Applicable to standard nodes only.
lnkacttime = 900                    ; Link activity timer time in seconds.
lnkactmacro = *59                   ; Function to execute when link activity timer expires.
;lnkacttimerwarn = 30seconds        ; Message to play when the link activity timer has 30 seconds left.

;remote_inact_timeout =             ; Specifies the amount of time without keying from the link. Set to 0 to disable timeout. (15 * 60)
;remote_timeout =                   ; Session time out for remote base. Set to 0 to disable. (60 * 60)
;remote_timeout_warning_freq =      ; 30
;remote_timeout_warning =           ; (3 * 60)

holdofftelem = 0                    ; Hold off all telemetry when signal is present on receiver or from connected nodes
telemnomdb = -3                     ; Telemetry Nominal Amplitude reference in dB
telemduckdb = -15                   ; Telemetry Ducking in dB when local or link voice tx in progress
telemdefault = 2                    ; 0 = telemetry output off
telemdynamic = yes                  ; yes = disallow users to change the local telemetry setting with a COP command
parrotmode = 0                      ; 0 = Parrot Off (default = 0)
parrottime = 1000                   ; Set the amount of time in milliseconds

; archivedir = /var/log/asterisk/recordings

;;; End of node-main template

[functions]
;;;; This section redacted from forum post

[telemetry]
ct1 = |t(350,0,100,2048)(500,0,100,2048)(660,0,100,2048)
ct2 = |t(660,880,150,2048)
ct3 = |t(440,0,150,4096)
ct4 = |t(440,0,75,1024)		; Unlinked CT
ct5 = |t(660,0,150,2048)
ct6 = |t(880,0,150,2048)
ct7 = |t(660,440,150,2048)	; Remote base CT
ct8 = |t(1047,0,75,1024)	; link traffic CT
ct9 = |t(1633,0,50,1000)(0,0,30,0)(1209,0,50,1000);

ranger = |t(1800,0,60,3072)(0,0,50,0)(1800,0,60,3072)(0,0,50,0)(1800,0,60,3072)(0,0,50,0)(1800,0,60,3072)(0,0,50,0)(1800,0,60,3072)(0,0,50,0)(1800,0,60,3072)(0,0,150,0)
remotemon = |t(1209,0,50,2048)                            ; local courtesy tone when receive only
remotetx = |t(1320,0,50,1024)(0,0,80,0)(1320,0,50,1024)   ; local courtesy tone when linked Trancieve mode
cmdmode = |t(900,903,200,2048)
functcomplete = |t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)
remcomplete = |t(650,0,100,2048)(0,0,100,0)(650,0,100,2048)(0,0,100,0)(650,0,100,2048)
pfxtone = |t(350,440,30000,3072)

patchup = rpt/callproceeding
patchdown = rpt/callterminated

[morse]
;;;;; Mores code ;;;;;
; Morse code parameters, these are common to all repeaters.
speed=20
frequency=500
amplitude=800
idfrequency=500
idamplitude=800

[wait-times]
; This section allows wait times for telemetry events to be adjusted
; A section for wait times can be defined for every repeater
telemwait = 1000                    ; Time to wait before sending most telemetry
idwait = 500                        ; Time to wait before starting ID
unkeywait = 1000                    ; Time to wait after unkey before sending CT's and link telemetry
calltermwait = 1000                 ; Time to wait before announcing "call terminated"

[macro100]
; Macros for hub use (no macros)

[macro101]
; Redacted from ASL forum post

[controlstates]
;;;;; Control states ;;;;;
; Allow several control operator functions to be changed at once using one command (good for scheduling)
;statenum = copcmd,[copcmd]... https://wiki.allstarlink.org/wiki/Rpt.conf#Control_States_Stanza
0 = rptena,lnkena,apdis,totena,ufena,noicd  ; Normal operation
1 = rptena,lnkena,apdis,totdis,ufena,noice  ; Net and news operation
2 = rptena,lnkdis,apdis,totena,ufena,noice  ; Repeater only operation

[schedule]
;;;;; Scheduler - execute a macro at a given time ;;;;;
;dtmf_function =  m h dom mon dow   ; ala cron, star is implied
;2 = 00 00 * * *                    ; at midnight, execute macro 2.

[dtmfkeys]
1004=K6DSA

[mdcmacro]
I1004=K1004

;;;;; The following are the active nodes and overrides on this server

;;;; AZ Main System

[401](node-main)		; Pinal Peak
rxchannel = voter/401		; RTCM
totime = 60000			; TOT to 60 seconds

[402](node-main)		; Mt. Lemmon
rxchannel = voter/402		; RTCM, a few of them
duplex = 2			; Non-local repeater for voter-simulcast system
dtmfkey=yes			; Enable PTT ID for testing purposes

[403](node-main)		; Heliograph Peak
rxchannel = voter/403		; RTCM

[404](node-main)		; Guthrie Peak
rxchannel = voter/404		; RTCM

[405](node-main)		; South Mountain (Alpine)
rxchannel = voter/405		; RTCM

[406](node-main)		; Cobbler Point (Nutrioso)
rxchannel = voter/406		; RTCM

[410](node-main)		; Greens remote base (No longer alive?)
duplex = 0			; Remote base, shotgun style
rxchannel = voter/410		; RTCM

;;;; AZ Southeast System

[451](node-main)		; Mule Mountain 
rxchannel = voter/451		; RTCM

[452](node-main)		; Sunsites
rxchannel = voter/452		; RTCM

[454](node-main)		; NW Tucson
rxchannel = voter/454		; RTCM

I still however have the issue of dtmfkeys accepting random key codes; for example if I dial a 5 it opens up the repeater, a 6 does not, MDC appears to work fine. With the posted configuration only code 1004 should open up the machine.

Excerpts from the console:

Connected to Asterisk 22.2.0+asl3-3.4.5-1.deb12 currently running on asterisk3 (pid = 2809534)
[2025-05-07 20:47:48.202] DTMF[2809584]: channel.c:4019 __ast_read: DTMF begin '6' received on voter/402
[2025-05-07 20:47:48.202] DTMF[2809584]: channel.c:4030 __ast_read: DTMF begin passthrough '6' on voter/402
[2025-05-07 20:47:48.343] DTMF[2809584]: channel.c:3905 __ast_read: DTMF end '6' received on voter/402, duration 127 ms
[2025-05-07 20:47:48.343] DTMF[2809584]: channel.c:3956 __ast_read: DTMF end accepted with begin '6' on voter/402
[2025-05-07 20:47:48.343] DTMF[2809584]: channel.c:3994 __ast_read: DTMF end passthrough '6' on voter/402
[2025-05-07 20:47:53.644] DTMF[2809584]: channel.c:4019 __ast_read: DTMF begin '5' received on voter/402
[2025-05-07 20:47:53.644] DTMF[2809584]: channel.c:4030 __ast_read: DTMF begin passthrough '5' on voter/402
[2025-05-07 20:47:53.824] DTMF[2809584]: channel.c:3905 __ast_read: DTMF end '5' received on voter/402, duration 178 ms
[2025-05-07 20:47:53.824] DTMF[2809584]: channel.c:3956 __ast_read: DTMF end accepted with begin '5' on voter/402
[2025-05-07 20:47:53.824] DTMF[2809584]: channel.c:3994 __ast_read: DTMF end passthrough '5' on voter/402
[2025-05-07 20:47:54.225] DEBUG[2810868]: app_rpt/rpt_telemetry.c:1060 rpt_tele_thread: Requested channel DAHDI/pseudo-919935163
[2025-05-07 20:47:54.225] DEBUG[2810868]: app_rpt/rpt_bridging.c:374 dahdi_conf_add: Channel DAHDI/pseudo-919935163 joining conference 1019
[2025-05-07 20:47:58.803] DEBUG[2809584]: app_rpt.c:3605 rxchannel_read: Got MDC-1200 (single-length) packet on node 402:
[2025-05-07 20:47:58.803] DEBUG[2809584]: app_rpt.c:3606 rxchannel_read: op: 01, arg: 80, UnitID: 1234
[2025-05-07 20:47:59.425] DEBUG[2810869]: app_rpt/rpt_telemetry.c:1060 rpt_tele_thread: Requested channel DAHDI/pseudo-1131243473
[2025-05-07 20:47:59.425] DEBUG[2810869]: app_rpt/rpt_bridging.c:374 dahdi_conf_add: Channel DAHDI/pseudo-1131243473 joining conference 1019
asterisk3*CLI>

I looks like the ASL3 code dropped one key bit of code from ASL2. Specifically, we don't have a default value for the dtmfkeys variable. Fortunately, there's an easy workaround until I can make the fix.

dtmfkey = yes
dtmfkeys = dtmfkeys

Does that take care of things?

That... absolutely fixed it! Fantastic, thanks so much for looking into this - glad to have this up and running again.

FYI, you can track the fix @ GitHub app_rpt: PR #679

1 Like