System Time Set using Radio DTMF

A means to set system clock with DTMF RADIO COMMANDS.

First I want to point out several things.
Read the warnings at the bottom.
This is not a perfect thing, but a framework to meet a end need.
You will likely need to make adjustments to it for your particular circumstance(s).

It was intended for Acid users who have no internet connection on their system but can be adapted to fit many situations.
While there are more than a dozen ways to do the same thing,
I chose this one to show to the group for the simplicity of implementation to those that are not as linux savvy, but have learned asterisk somewhat.

If you are in the US and have had the same system running for many years without updating the zoneinfo files, you should do that and copy the new timezone file to your /etc/localtime because the Daylight Savings Time that changed a few years ago (again) has probably been giving you some frustration on the time change twice or four times a year.  More info on that on the web:

SO, I am implementing this from the phone patch. Using the default dial to open the patch.

By default, (*6) +A+ HHMM is all the dtmf you would need to enter the time in 24hr format. Example *6A1345 will set the clock to 1:45pm

I chose ‘A’ as the dialing catch since it’s unlikely to be in your normal phone extensions and is intended for ‘no internet service’ installs set by RADIO.

If there are not 4 numbers to follow the “A”, it will fall through, otherwise it will say ‘the-time-is’, the four numbers you are setting, then pause for 10 seconds to allow you to hang-up ( *0 ) if you wish to cancel before it sets time and reboots your machine.

If you are trying to sync it to the second, enter it 15 seconds before the top of a minute (a 20 sec head start). Because asterisk always runs with a match as soon as it appears. So that would start running on the last/4th dtmf time digit (5th digit entered) after the phone patch prefix, not when you unkey the radio.

In extensions.conf  just under [radio]

exten = _Axxxx,1,Goto(set_time_clock|${EXTEN:1}|1)   ;set time, send to subscript without leading digit

(place the rest at the end of extensions.conf file….)

[set_time_clock]; by kb8jnm
exten =_X.,1,Wait(5)
exten =_X.,2,Playback(rpt/thetimeis)
exten =_X.,3,SayAlpha(${EXTEN})       ; Read back Dialed Number for time
exten =_X.,4,Wait(10)                  ; allow 10 seconds to hang-up (*0 ) if not correct
exten =_X.,5,System(date +%T -s \”${EXTEN:0:2}:${EXTEN:2:2}:00\”) ;format ‘HH:MM:00’ – 24hr format
exten =_X.,6,System(reboot)
exten =_X.,7,Hangup

Adjusting the timeclock on a live system can have unknown affect on things that are running  & relying on timers.

What is not a problem now could be a problem latter depending on your cron and sched settings for what is currently active on the system.

If you have much a time slippage in your clock, adjust it more often or when it gets 2 minutes or so out of time.

So at a minimum, shutdown links before adjusting the clock. My remedy for this was a reboot after setting.
I am thinking of you folks that have unconnected mountain top systems you can’t get to if a problem arises.
So, To avoid many unexpected problems that can occur in system timers mis-match, the system will reboot right after setting the clock.

I suggest you leave ‘REBOOT’ in place unless you have good reason to take it out. But you have been warned.

If you like it… great… if you don’t like it… make it better and shove it out to the group for others to improve on.
Probably better to hand the extension data off to a shell script, shutdown asterisk, set-clock, restart asterisk & exit. But not if you use cron for all your app_rpt and system scheduling needs.
But this is simple and with the full reboot, resets ‘all’ system timers before ‘any’ can be a problem. Unless you change that.

Sync time with NTP for app_rpt

(internet connected systems only)

While this probably should be done by your OS, from cron

Here is a script to sync your time with NTP.

Give  it a name ( , Apply ownership

Give it a command in rpt.conf, Run that command  from the macro/sched late at night.

/usr/sbin/ntpdate > /etc/asterisk/log/timelog.txt

Will also create a log file if you need to check that it has been running correctly.
If not needed, delete all after and including ">"
Hopefully these are more of a example of how to do other things for those that are learning.

Macro Delay Execution Timer

This script was created to execute a  delay then a command.

Meaning that you issue a command as part of some other simple or complex function and have a delay before it executes a second part or a cancellation of the same.

It could have a multitude of applications once you understand what it is actually doing. But for our example here, it is a simple one.

Our example, we have a light that we use to light our way from the repeater site at night and often someone using it for access to or from the repeater site at night forgets to turn it off. So we need a auto-turn-off for this light-up function.


We are calling the script

If you are using this for many things or nodes, make each instance a unique name with node number and/or special function name.

Create a command for the script in rpt.conf

XXXX=cmd, etc/asterisk/myscripts/

Now our macro for calling the “turn light on” looks like this before we start:


55= *9987 *9988# ; (play file” light-on” and switch parallel port pin 5 on)

56= *9989 *9990# ; (play file “light-off” and switch par port pin 5 off)


55= *9987 *9988 *XXXX# ;insert your script command issued above

Edit the script and set the timer in seconds and call the macro that turns it off when the timer has expired.

Make the script 775 ownership.

DOWNLOAD as a file

# mike/kb8jnm –
# create delay / run command
# make a command for this script, call it from a macro string
# set wait time in seconds
sleep 1200
# execute command (calling a macro to shut off the called function)
# format is – rpt fun NODE# CMD#
asterisk -rx “rpt fun 29283 *556
# will clean exit after waiting and executing

# end of file EOF

This simple example is just to show functionality. Use your imagination to fit your need.  Be careful not to put it in a situation where it could be called multiple times in automation.

Barry, G8SAU Used it for this…

I have made a repeater mast head pre-amp control
that users can enable turn on with a DTMF code  eg *51 that gives a boost 
to the RX for a period of 30 mins then reverts to OFF

for those moments that need extra coverage on RX when Fixed user is working 
a Mobile user or an HT user on the edge of coverage, RX wise.

Script – Initial ID / Normal ID

Many of us that are use to the older premium  “hard-wire” style repeater controller are also use to having a initial ID that would allow for a separate ID to be played when the repeater was keyed for the first time from a sleep state.

Then afterwards, would play a normal ID at “id-interval” timing that would be a short ID for in-use.

Most of us would use that Initial ID to play a long ID stating extended info about the repeater like location information so when someone stumbled on the repeater late at night or when nobody was around to ask, they would have the correct info about which repeater they were accessing and where it was.

While there was limited ways to accurately obtain this info and act on it in a way that was uncomplicated for a control-op to install correctly and use, I took it to task.

This is totally a Bash Script that needs to be run from start-up
or from a command line (should do for testing beforehand).
Made/Tested with ACID.

Here is the result.

You need two audio files of the ID's before you start.
Here called "idmsg1" (initial/sleep id)
& "idmsg2" (wake/regular id) and 
our actual id message is "idmsg"
You can just take one of those files and copy ( cp ) it to a new filename for idmsg 
like this:  cp idmsg1.wav idmsg.wav
(assuming you are in the directory of the files)

I'll call the shell script
If running multi-nodes on a single server, you might want to make a new filename like:
so you can have separate id's for each nodes.
This would mean making a script for each node and running a new process for each.
If you do this, change the /tmp/init-id.txt located in "two places" in the
file to the same unique format.

In rpt.conf
You need to give it a command:ex

Use the startup macro to call it:ex

You need to edit before running:
Node number
files and locations of your 2 id files and the /location/name of your voice-id file
(idrecording =/etc/asterisk/msg/idmsg) in both locations in the script.
Pay close attention to spaces when editing as it will change things in error.

Make the files & script we are using 775 ownership

(from a shell)
cd /etc/asterisk/myscripts (where located)
./  ( ./ with actual name you use .sh)
and you use <ctrl> + C to break and stop it from command line running it.
change sleep number to 20 for command line testing and 200 when auto
loading to limit file accesses. 
I'm Assuming a 5 minute or better id interval.

Do pay close attention to spaces in the file when editing.
You will create errors if not and not understand where from.

Download as File

At the bottom of this page is shown what the response will look like from a command line.

When needed, the script simply 
copies idmsg1 to idmsg (sleep/init-id)
copies idmsg2 to idmsg (wake/normal-id)
But will not attempt to write while ID is playing. ider_state=0

# - mike/kb8jnm
# overwrite id files to create initial id & regular id
# based on app_rpt - "ider_state" variable.
# make ownership of this file 775
# -See sleep ### at the bottom is in seconds.
# Lower the value to 20 for testing live from a command line.
# You will see the updates faster.

# preset some parms

# this is a infinate loop
while :

# read our parms for node - put in text file - (edit node number)
 asterisk -rx "rpt xnode 29283" > /tmp/init-id-29283.txt

# parse our parms from that file and only rewrite id if it needs it
 while read line
 echo $line

 if [ "$line" = "$idsleep" ] && [ "$idis" = "wakeid" ]; then
# edit locations and names next line
 cp /etc/asterisk/msg/idmsg1.wav /etc/asterisk/msg/idmsg.wav
 echo " ** " $line $idsleep "-init ID"
 if [ "$line" = "$idwake" ] && [ "$idis" = "sleepid" ]; then
# edit locations and names next line
 cp /etc/asterisk/msg/idmsg2.wav /etc/asterisk/msg/idmsg.wav
 echo " ** " $line $idwake "-normal ID"
 done </tmp/init-id-29283.txt

# show status if running from a command line for test
echo "ID IS " $idis

# wait a bit to limit file access (in seconds)
sleep 200


If everything is working fine, 
you will see something like this at a command line
when you execute it:

RPT_NUMLINKS=1     ;these are parms returned by app_rpt on xnode

ider_state=2       ;when our script sees this line it acts.
 **  ider_state=2 ider_state=2 -init ID     ;these are echos of internal vars

ID IS  sleepid      ;this is a echo of internal var of current state.

Don't forget to check your timers...
totime=600000 ;in milisoconds 300000=5min
idtime=590000 ; in 10ms
politeid=500000 ; =8m20s
sleeptime=1830 ;in seconds 300=5m

ID and Tail Msg Recorder via app_rpt

If you got here from a search engine, you “will need” to read the beginning to understand how to use this info by going to

Do not proceed unless you read this in it’s entirety. Make back-up files before editing anything. I offer no support. Use at your own risk.

We shall start with the ivr.conf custom extension file with our toy, recording and selecting between 2 system ID’s and 5 selectable Tail messages, 3 selectable aux msgs via the repeater system:

aux msgs are still just tail messages. I named them differently to separate purpose.

So I can keep ecom messages stored there and turn them into rotation when needed.

There is no dual rotation between them. One at a time based on the “tailmessagelist=” in rpt.conf for both  tmsg and auxmsg.

First, make a directory under /etc/asterisk called “msg”

 /etc/asterisk/msg and change ownership of  directory to 775

Second, edit rpt.conf and under the node stanza, add these lines:

idrecording =/etc/asterisk/msg/idmsg

tailmessagelist=/etc/asterisk/msg/tmsg1,/etc/asterisk/msg/tmsg2,/etc/asterisk/msg/tmsg3,/etc/asterisk/msg/tmsg4,/etc/asterisk/msg/tmsg5,/etc/asterisk/msg/auxmsg1,/etc/asterisk/msg/auxmsg2,/etc/asterisk/msg/auxmsg3 ;tail message list, if not present, will go to next one that is.

Now for the contents of ivr.conf:

[ivrmenu] ;important first line. our *97 cmd example used context  ivrmenu, this brings *97 cmds to this page.

; the beginning menu sorts and routes extensions to a new stanza
; place commands above the readback you don’t want to be read back on the air with one line…

; cmd#,1,Goto( newstanza below the error trap)

; this will be more important when we add other stuff later.

; exten => _X.,1,Noop() ; there must be a 1st instruction if you comment out the readback

exten =>_X.,1,SayAlpha(${EXTEN}) ; Readback Dialed Number

; evaluate the extension route to new stanza
exten => 10,2,Goto(sys-msgs,10,1) ;tmsg1 play
exten => 11,2,Goto(sys-msgs,11,1) ;tmsg1 rec
exten => 12,2,Goto(sys-msgs,12,1) ;tmsg1 off
exten => 13,2,Goto(sys-msgs,13,1) ;tmsg1 on
exten => 20,2,Goto(sys-msgs,20,1) ;tmsg2
exten => 21,2,Goto(sys-msgs,21,1)
exten => 22,2,Goto(sys-msgs,22,1)
exten => 23,2,Goto(sys-msgs,23,1)
exten => 30,2,Goto(sys-msgs,30,1) ;tmsg3
exten => 31,2,Goto(sys-msgs,31,1)
exten => 32,2,Goto(sys-msgs,32,1)
exten => 33,2,Goto(sys-msgs,33,1)
exten => 40,2,Goto(sys-msgs,40,1) ;tmsg4
exten => 41,2,Goto(sys-msgs,41,1)
exten => 42,2,Goto(sys-msgs,42,1)
exten => 43,2,Goto(sys-msgs,43,1)
exten => 50,2,Goto(sys-msgs,50,1) ;tmsg5
exten => 51,2,Goto(sys-msgs,51,1)
exten => 52,2,Goto(sys-msgs,52,1)
exten => 53,2,Goto(sys-msgs,53,1)
exten => 60,2,Goto(sys-msgs,60,1) ;idmsg1 play
exten => 61,2,Goto(sys-msgs,61,1) ;idmsg1 rec
exten => 62,2,Goto(sys-msgs,62,1) ;idmsg2 pl
exten => 63,2,Goto(sys-msgs,63,1) ;idmsg2 rec
exten => 67,2,Goto(sys-msgs,67,1) ;activate id1
exten => 68,2,Goto(sys-msgs,68,1) ;activate id2
exten => 69,2,Goto(sys-msgs,69,1) ;playback active id
exten => 70,2,Goto(sys-msgs,70,1) ;auxmsg1 pl
exten => 71,2,Goto(sys-msgs,71,1) ;auxmsg1 rec
exten => 72,2,Goto(sys-msgs,72,1) ;auxmsg1 off
exten => 73,2,Goto(sys-msgs,73,1) ;auxmsg1 on
exten => 80,2,Goto(sys-msgs,80,1) ;auxmsg2
exten => 81,2,Goto(sys-msgs,81,1)
exten => 82,2,Goto(sys-msgs,82,1)
exten => 83,2,Goto(sys-msgs,83,1)
exten => 90,2,Goto(sys-msgs,90,1) ;auxmsg3
exten => 91,2,Goto(sys-msgs,91,1)
exten => 92,2,Goto(sys-msgs,92,1)
exten => 93,2,Goto(sys-msgs,93,1)
exten => 97,2,Goto(sys-msgs,97,1);turn-off-all-voice msgs except IDmsg

; end of presort/route to new stanza for valid commands

; error trap if extension falls through

exten =_X.,2,Playback(option-is-invalid&silence/1) ;trap for bad#’s
exten =_X.,n,Playback(silence/1&vm-goodbye)
exten =_X.,n,Hangup


; the above presorted all commands for msgs to [sys-msgs] (important if we include all the toys later)


[sys-msgs] ; keep this stanza at the end of the file
exten => 10,1,Playback(/etc/asterisk/msg/tmsg1.wav)
exten => 10,n,Hangup
exten => 11,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 11,n,Record(/etc/asterisk/msg/tmsg1:wav)
exten => 12,1,System(mv -f /etc/asterisk/msg/tmsg1.wav /etc/asterisk/msg/tmsg1-off.wav)
exten => 12,2,Playback(message-number&letters/t&digits/1&removed)
exten => 13,1,System(mv -f /etc/asterisk/msg/tmsg1-off.wav /etc/asterisk/msg/tmsg1.wav)
exten => 13,2,Playback(message-number&letters/t&digits/1&restarting)

exten => 20,1,Playback(/etc/asterisk/msg/tmsg2.wav)
exten => 20,n,Hangup
exten => 21,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 21,n,Record(/etc/asterisk/msg/tmsg2:wav)
exten => 22,1,System(mv -f /etc/asterisk/msg/tmsg1.wav /etc/asterisk/msg/tmsg2-off.wav)
exten => 22,2,Playback(message-number&letters/t&digits/2&removed)
exten => 23,1,System(mv -f /etc/asterisk/msg/tmsg2-off.wav /etc/asterisk/msg/tmsg2.wav)
exten => 23,2,Playback(message-number&letters/t&digits/2&restarting)

exten => 30,1,Playback(/etc/asterisk/msg/tmsg3.wav)
exten => 30,n,Hangup
exten => 31,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 31,n,Record(/etc/asterisk/msg/tmsg3:wav)
exten => 32,1,System(mv -f /etc/asterisk/msg/tmsg3.wav /etc/asterisk/msg/tmsg3-off.wav)
exten => 32,2,Playback(message-number&letters/t&digits/3&removed)
exten => 33,1,System(mv -f /etc/asterisk/msg/tmsg3-off.wav /etc/asterisk/msg/tmsg3.wav)
exten => 33,2,Playback(message-number&letters/t&digits/3&restarting)

exten => 40,1,Playback(/etc/asterisk/msg/tmsg4.wav)
exten => 40,n,Hangup
exten => 41,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 41,n,Record(/etc/asterisk/msg/tmsg4:wav)
exten => 42,1,System(mv -f /etc/asterisk/msg/tmsg4.wav /etc/asterisk/msg/tmsg4-off.wav)
exten => 42,2,Playback(message-number&letters/t&digits/4&removed)
exten => 43,1,System(mv -f /etc/asterisk/msg/tmsg4-off.wav /etc/asterisk/msg/tmsg4.wav)
exten => 43,2,Playback(message-number&letters/t&digits/4&restarting)

exten => 50,1,Playback(/etc/asterisk/msg/tmsg5.wav)
exten => 50,n,Hangup
exten => 51,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 51,n,Record(/etc/asterisk/msg/tmsg5:wav)
exten => 52,1,System(mv -f /etc/asterisk/msg/tmsg5.wav /etc/asterisk/msg/tmsg5-off.wav)
exten => 52,2,Playback(message-number&letters/t&digits/5&removed)
exten => 53,1,System(mv -f /etc/asterisk/msg/tmsg5-off.wav /etc/asterisk/msg/tmsg5.wav)
exten => 53,2,Playback(message-number&letters/t&digits/5&restarting)

exten => 60,1,Playback(letters/i&letters/d&vm-message&digits/1)
exten => 60,n,Playback(/etc/asterisk/msg/idmsg1.wav)
exten => 60,n,Hangup
exten => 61,1,Playback(please-enter-your&letters/i&letters/d&vm-message&digits/1&after-the-tone&silence/3)
exten => 61,n,Record(/etc/asterisk/msg/idmsg1:wav)

exten => 62,1,Playback(letters/i&letters/d&vm-message&digits/2)
exten => 62,n,Playback(/etc/asterisk/msg/idmsg2)
exten => 62,n,Hangup
exten => 63,1,Playback(please-enter-your&letters/i&letters/d&vm-message&digits/2&after-the-tone&silence/3)
exten => 63,n,Record(/etc/asterisk/msg/idmsg2:wav)

exten => 67,1,Playback(letters/i&letters/d&vm-message&digits/1&activated&silence/2)
exten => 67,n,System(cp -f /etc/asterisk/msg/idmsg1.wav /etc/asterisk/msg/idmsg.wav)

exten => 68,1,Playback(letters/i&letters/d&vm-message&digits/2&activated)
exten => 68,n,System(cp -f /etc/asterisk/msg/idmsg2.wav /etc/asterisk/msg/idmsg.wav)

exten => 69,1,Playback(activated&letters/i&letters/d)
exten => 69,n,Playback(/etc/asterisk/msg/idmsg)
exten => 69,n,Hangup

exten => 70,1,Playback(/etc/asterisk/msg/auxmsg1.wav)
exten => 70,n,Hangup
exten => 71,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 71,n,Record(/etc/asterisk/msg/auxmsg1:wav)
exten => 72,1,System(mv -f /etc/asterisk/msg/auxmsg1.wav /etc/asterisk/msg/auxmsg1-off.wav)
exten => 72,2,Playback(message-number&letters/a&digits/1&removed)
exten => 73,1,System(mv -f /etc/asterisk/msg/auxmsg1-off.wav /etc/asterisk/msg/auxmsg1.wav)
exten => 73,2,Playback(message-number&letters/a&digits/1&restarting)

exten => 80,1,Playback(/etc/asterisk/msg/auxmsg2.wav)
exten => 80,n,Hangup
exten => 81,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 81,n,Record(/etc/asterisk/msg/auxmsg2:wav)
exten => 82,1,System(mv -f /etc/asterisk/msg/auxmsg2.wav /etc/asterisk/msg/auxmsg2-off.wav)
exten => 82,2,Playback(message-number&letters/a&digits/2&removed)
exten => 83,1,System(mv -f /etc/asterisk/msg/auxmsg2-off.wav /etc/asterisk/msg/auxmsg2.wav)
exten => 83,2,Playback(message-number&letters/a&digits/2&restarting)

exten => 90,1,Playback(/etc/asterisk/msg/auxmsg3.wav)
exten => 90,n,Hangup
exten => 91,1,Playback(please-enter-your&vm-message&after-the-tone)
exten => 91,n,Record(/etc/asterisk/msg/auxmsg3:wav)
exten => 92,1,System(mv -f /etc/asterisk/msg/auxmsg3.wav /etc/asterisk/msg/auxmsg3-off.wav)
exten => 92,2,Playback(message-number&letters/a&digits/3&removed)
exten => 93,1,System(mv -f /etc/asterisk/msg/auxmsg3-off.wav /etc/asterisk/msg/auxmsg3.wav)
exten => 93,2,Playback(message-number&letters/a&digits/1&restarting)

exten => 97,1,Playback(message-number&all&removed); not idmsg
exten => 97,n,System(mv -f /etc/asterisk/msg/tmsg1.wav /etc/asterisk/msg/tmsg1-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/tmsg1.wav /etc/asterisk/msg/tmsg2-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/tmsg3.wav /etc/asterisk/msg/tmsg3-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/tmsg4.wav /etc/asterisk/msg/tmsg4-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/tmsg5.wav /etc/asterisk/msg/tmsg5-off.wav)
;exten => 97,n,System(mv -f /etc/asterisk/msg/idmsg.wav /etc/asterisk/msg/idmsg-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/auxmsg1.wav /etc/asterisk/msg/auxmsg1-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/auxmsg2.wav /etc/asterisk/msg/auxmsg2-off.wav)
exten => 97,n,System(mv -f /etc/asterisk/msg/auxmsg3.wav /etc/asterisk/msg/auxmsg3-off.wav)

Some of this structure may not make sense at this point in time but as long as you can see how we are doing it all, you may have better ideas. If you are not fair working with asterisk, just use it the way I have laid it out. Some of the weird structure is because we will be adding things as we go along. Some may not be posted for some time…

Most important first step is record idmsg1 (*97 61) and set it active ( *97 67) 

So the way this part works is (how to use):

Tail messages rotate whatever msgs in the list from above that are present. If not present, they are skipped. When you deactivate a msg (off), it renames it xxxx-off.wav so it will not be seen by the list and not played. When you reactivate that msg, it renames it back to the original filename. I will say that recording works best from a pc using iaxrpt or a sip phone and a good mic.

*9711 will record a tail msg #1 named tmsg1.wav in the diectory /etc/asterisk/msg/

when finished, you need to exit, you will need to patch-hang-up  ” *0 ”

*9710 will playback the tmsg1 we just recorded. You do not need to activate a tail or aux msg unless you have deactivated it and now want it to play.

Test it all out and record all of your messages. Much easier than audicity.

Format of command: (to make easy to remember)

*97 (ivr) 1/2/3/4/5/6/7/8/9 (msg#) 0/1/2/3 (play, rec, off, on )

*97 97 will deactivate all t-msg and aux-msgs.

You can not deactivate voice id. You can change from recorded idmsg1 to idmsg2 or back.

After recording a idmsg 1 & 2, you need to manually select which one is to be used for id or you will not have a voice id and the cw id will not run when id has been set to voice (except cwid at id-over-activity) When you select id-msg#, you are making a copy of the file selected and naming it “idmsg.wav” which is what our settings are in rpt.conf

I would suggest you do not change the script until you make it run once and you fully understand asterisk dialplan rules. I am sure someone can make a much better script than I once they have realized how I got app_rpt to do some functions on asterisk that app_rpt has control of.

However, it is possible to macro/script a method to change id’s from idmsg1/idmsg2 using the scheduler for flexability. Sorry, not going there on this page. Just giving you the idea. But you now have assignable commands for macro/sched to work.

So, a short story as how I might use this: While at any time, there may be various tmsgs on and I don’t want to find out what is on and off when a ecom event happens. I would use *97 97 to turn them all off and then select one of the auxmsgs to be turned on that I have stored as ecom msgs.

If you have ssh or ftp access, you can look in /etc/asterisk/msg/ for those tmsgs or auxmsg that are turned off.

They will show that in their filename  ex: tmsg5-off.wav

Other notes:

My advise to most of you is to reduce the number of tail msgs to 3 and aux msgs to 1 or 2 and reduce the tailmessagetime to 720,000. You can do this in tailmessagelist without changing the code above. It should be plenty. When a tmsg is off, it is skipped but you will not get a new tail message to speak until the timer has elapsed again and a message is found that is on.  So if you only have one of 8 active, it could be quite a while before one of them is actually spoken. Sorry, that is hard wired in app_rpt. Adjust all of this to suite you needs based on how many active tail messages you will generally have on and how many is in your list. Set timer appropriately.

A more likely good scenario is to have only 3 tmsgs recorded and in the list and select only one of them per day/hour/week and changed by sched/macro as needed. For this I would use a timer of about 5 min. So the one would play every 15 min. Just an example.

This is all slightly crude but it works.

My timers/settings:

(5 active tail msgs)

tailmessagetime=9000000 ; 15 minutes between tail messages
tailsquashedtime=240000 ; If squashed by another user, try again after 4 min

idtime=600000 ; in 10ms = 10 min
politeid=500000 ;8m20s
sleeptime=1830 ;in seconds 300=5min


IP Address Readback via command

If you got here from a search engine, you “will need” to read the beginning to understand how to use this info by going to

Do not proceed unless you read this in it’s entirety. Make back-up files before editing anything. I offer no support. Use at your own risk.

Here is a IP address readback by command. This has been set to route to speak-ip before the extension is played-back. Look at the code and you will understand how simple it is. The difference between this and the one that may have been shipped with your default acid install files is that it is completely quite.
Just the ip is red back over the air. No dial tone, no ct.
[ivrmenu] ;the beginning menu sorts and routes extension to a new stanza
; pre-evaluate extensions and route to new stanza past error trap
; The first extensions to prevent extension read-back for certain commands
exten =>00,1,Goto(speak-ip,1,1)  ; command is 00 and is the 1st instruction sent to stanza below
;- this ends quite mode
exten =>_X.,1,SayAlpha(${EXTEN})       ; Readback Dialed Number
; error trap:  If command fell through, speak an error
exten =_X.,2,Playback(option-is-invalid&silence/1&please-contact-tech-supt)
exten =_X.,n,Playback(silence/1&vm-goodbye)
exten =_X.,n,Hangup
; this ends pre-evaluate in routing to new stanza
; New stanzas to be placed below the error trap


Don’t forget to save your file and restart asterisk.

So just key and enter  ” *97  00 ”  for it to work.

Toys For app_rpt (acid)

Well, it is about time for me to begin posting some of the toys I have built for app_rpt.

I have quite a few so I shall show them in a way that they will be organized as a whole.

You may take from what I have done and change them to work your purpose in your own way but I will cation you, when I have posted them all, you will wish you had some organization to it all.

I will only be posting one at a time. I will post as much info as I can but offer no support. Please get/use a copy of the asterisk manual to understand more about how many of the things here are accomplished.

Some of you more familiar with asterisk might ask why I did not do things in other ways and the short answer to that is that app_rpt has a interfering control over some asterisk functions. Work-a-rounds were needed. You are welcome to take what I have done here and make it better.

In time, I will post how to do your own message recording through your system and eventually add voice recognition and tie that to artificial intelligence for a siri like interface I call “Peater-Stein” (rePeater einStein) .  But all in time (I don’t seem to have enough of that)

Use at you own risk. Make back-ups of your config files before editing them.

So here we go…

The first thing you will need to do to keep all of these organized is keep them all in a separate command  file.

We shall do this by adding a statement to the bottom of our extensions.conf file like this:

#includeifexists custom/ivr.conf

This means we will need to create a directory in/under asterisk called “custom” and create a file named “ivr.conf” in that sub-directory – So the full path of the new file would look like this:


We will begin to build out all of our custom toys in this file. But first, we need a command prefix we will use in routing what we do in this file exclusively so you should not be using *97 or the context ivrmenu anywhere else.

So in rpt.conf  – add a line like this or change the command to something else totally unique.


This will direct app_rpt to seek extentions starting with *97xxxx and handle them like a autopatch with no CT or dialtone following the” ivrmenu” context and we shall answer all of them all in ivr.conf because that is where the context “ivrmenu” will be found.

At a command line, you can proceed to the directory

/etc/asterisk/custom/  and type

nano ivr.conf

place the following line first in the file… and the rest to follow…

[ivrmenu] ; 1st line.  *97 cmd uses context  ivrmenu – brings *97 cmds to this page/stanza.

; the beginning menu sorts and routes extension to a new stanza

; pre-evaluate – first extensions to prevent extension read-back for certain commands
; format of commands in this quite spot must be cmd,1 (first instruction)
;- this ends quite mode
exten =>_X.,1,SayAlpha(${EXTEN})       ; Readback Dialed Number
; format of commands in this spot must be cmd, (second instruction)
; Error trap – If command fell through, speak an error
exten =_X.,2,Playback(option-is-invalid&silence/1&please-contact-tech-supt)
exten =_X.,n,Playback(silence/1&vm-goodbye)
exten =_X.,n,Hangup
; this ends pre-evaluate in routing to new stanza

Save and exit. You have created the file we will use.

Here are some of the toys we will put in there (links will show when pages are done)

IP address readback via command

ID and Tail MSGs Recorder via app_rpt

EchoNode lookup/readback live by command

Voice recognition via app_rpt

Word speller via voice recognition (not useful but example of concept)

System command via voice recognition

Artificial Intelligence for your repeater – Peater-Stein


App-rpt resources on the web

These are a list of helpful resources on the web.

I’ll add to it from time to time.

System Admin Guide

Most important link for info for reference is  –

For help with app_rpt, jump onto the email reflector.



Download the centos/app_rpt package

Source Code SVN:

Source Asterisk

Source Limey

Source ACID


App_Rpt for Beagle Board Black ( BBB ) by WA3DSP-Doug


ADD-ON Toys and Apps

A WX Alert Script  for ACID

A collection of apps by K0KN


Sometime by winter 2014, I will post many apps/toys I have built for app_rpt

Writing the how-to’s can take some time.   …73

COP iLink Status and Remote Command List

A Internal Command list For app_rpt (incomplete)
More is added from time to time. Some,not all default assignments shown.

An important note that I’m going to repeat for those that stumbled on this page without having read the others:

It is important to “organize” your commands so that you do not partially “dupe” a command.

I suggest keeping them in numerical order so it can be easily seen. Here is a example:

8900=cop,24   ; cancel localplay stream +/- telemetry

8901=localplay,/var/lib/asterisk/sounds/wx/wxfc    ;my custom wx script player example

8902=localplay,/var/lib/asterisk/sounds/wx/wxalert    ;my custom wx alert script player example

90=cop,1          ;warm boot
91=cop,2           ; System enable – you should not comment these out in a live system
92=cop,3        ; System disable

99=cop,6          ; Remote sip/telephone PTT key command  (# to unkey)

If I were to assign a command of *89 to anything, the above 4 digit 8901, 8902 would never execute. Unlike conventional controllers, asterisk will run with and execute the first match it gets.  So if there were a command created for *89,  *89 would always execute and” never ” execute a 3 or four digit command starting with *89.

So if you find yourself in this dilemma, make all *89 commands 3 or 4 digit commands to avoid it. Keeping them in order on your command list helps avoid the problem in the first place.

Saying that,  here is my list of assignable commands I have compiled over time.

Status Commands

80=status,1       ; Force id global
81=status,2       ; Time
82=status,3       ; Give Software ver Global

=status,11   ; Force ID (local only)
=status,12   ; Give Time of Day (local only)

87=status,15    ; global node query (reads back all nodes connected in the network

iLink Commands

=ilink,1 – Disconnect specified link
=ilink,2 – Connect specified link — monitor only
=ilink,3 – Connect specified link — transceive
=ilink,4 – Enter command mode on specified link

70=ilink,5        ; Link Status (long)
71=ilink,6        ; Disconnect All Links

=ilink,11 – Disconnect a previously permanently connected link
=ilink,12 – Permanently connect specified link — monitor only
=ilink,13 – Permanently connect specified link — transceive

73=ilink,15       ; Full Sys Status (all nodes)
74=ilink,16       ; Reconnect Links (that were disconnected by command)

=ilink,200 thru 215 – (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)

Control Operator ( COP ) Commands
Keep in mind, some commands only valid under certain configurations.

=cop,1       ;warm boot
=cop,2       ; System enable
=cop,3       ; System disable
=cop,4        ; Test tone on/off – or # to end
=cop,5        ; Dump system variables on console (debug use only)
=cop,6          ; Remote base telephone tx cntl key
=cop,7        ; Time out timer enable
=cop,8        ; Time out timer disable
=cop,9        ; Autopatch enable
=cop,10        ; Autopatch disable
=cop,11        ; User linking functions enable
=cop,12            ; User linking functions disable
=cop,13        ; Query system control state
=cop,14        ; Set system control state
=cop,15        ; Scheduler enable
=cop,16        ; Scheduler disable
=cop,17        ; User functions enable (time, id, etc)
=cop,18        ; User functions disable
=cop,19        ; Select alternate hang time (althangtime)
=cop,20        ; Select standard hangtime (hangtime)
=cop,21     ; Enable Parrot
=cop,22     ; Disable Parrot
=cop,23     ; Bird Bath – Clean Residual stream  -also see cop 55
=cop,24     ; flush all pending telemetry in the buffer
=cop,25 ; return last node which unkeyed from any connected node (directly or indirectly)
=cop,26 ; Query all nodes which keyed or unkeyed from any connected node (directly or indirectly)

=cop,27   ; Reset DAQ minimum on a pin
=cop,28   ; Reset DAQ maximum on a pin
=cop,30   ; Recall Memory Setting in Attached Xcvr
=cop,31   ; Channel Selector for Parallel Programmed Xcvr

=cop,32     ; DTMF Pad test – end with #
=cop,33     ; Local Telemetry Output Enable
=cop,34     ; Local Telemetry Output Disable
=cop,35     ; Local Telemetry Output on demand

=cop,36     ; Foreign Link Local Output Path Enable
=cop,37     ; Foreign Link Local Output Path Disable
=cop,38     ; Foreign Link Local Output Path Follows Local Telemetry Selection (above)
=cop,39     ; Foreign Link Local Output Path Timed

=cop,40     ; IRLP announce Enable
=cop,41     ; IRLP announce Disable
=cop,42     ; Echolink announce node # only
=cop,43     ; Echolink announce node Callsign only
=cop,44     ; Echolink announce node # & Callsign
=cop,45     ; Link Activity timer enable        -LATENA
=cop,46     ; Link Activity timer disable        -LATDIS
=cop,47 ; Reset”Link Config Changed”Flag -none -change link state without arming activity timer

=cop,48 – Send Page Tone (Tone specs separated by parenthesis)
=cop,49 – Disable incoming connections (control state noice)
=cop,50 – Enable incoming connections (control state noicd)

=cop,51  ; Enable Sleep Mode
=cop,52  ; Disable Sleep Mode
=cop,53  ; Awaken from Sleep
=cop,54  ; Go back to sleep when the TX carrier drops
=cop,55     ; Parrot Once Command
=cop,58        ;Tx CTCSS On Input only Enable (also see itxctcss=1)
=cop,59        ;Tx CTCSS On Input only Disable

=cop,61,pp3=0 ; parallel port control: pp+pin number + 0 or 1 for on/off

=cop,80     ; Change Default Squelch Code (Xelatec)

Remote Base – default assignments shown

0=remote,1          ; Retrieve Memory
1=remote,2          ; Set freq.
2=remote,3          ; Set tx PL tone
3=remote,4          ; Set rx PL tone
40=remote,100       ; Rx PL off
41=remote,101       ; Rx PL on
42=remote,102       ; Tx PL off
43=remote,103       ; Tx PL on
44=remote,104       ; Low Power
45=remote,105       ; Medium Power
46=remote,106       ; High Power
711=remote,107      ; Bump -20
714=remote,108      ; Bump -100
717=remote,109      ; Bump -500
713=remote,110      ; Bump +20
716=remote,111      ; Bump +100
719=remote,112      ; Bump +500
721=remote,113      ; Scan – slow
724=remote,114      ; Scan – quick
727=remote,115      ; Scan – fast
723=remote,116      ; Scan + slow
726=remote,117      ; Scan + quick
729=remote,118      ; Scan + fast
79=remote,119       ; Tune (brief AM transmission for automatic antenna tuner)
51=remote,5         ; Long status query
52=remote,140        ; Short status query
67=remote,210       ; Send a *
69=remote,211       ; Send a #

; Remote base login.
; Define a different dtmf sequence for each user which is
; authorized to use the remote base to control access to it.
; For examble 9139583=remote,99,WB6NIL,G would grant access to
; the remote base and announce WB6NIL as being logged in.
; Another entry, 9148351=remote,99,WA6ZFT,E would grant access to
; the remote base and announce WA6ZFT as being logged in.
; When the remote base is disconnected from the originating node, the
; user will be logged out. The LICENSETAG argument is used to enforce
; tx frequency limits. See [txlimits] below.

200 thru 215 – (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)


Here is handy command to run any script calling system commands that you can later call from a macro/scheduler.

XXX=cmd,/some/were/in/your/  ;example to call a script by dtmf command

app_rpt COS and PTT through Parallel Port

This skinny direction set is only for the ACID distribution of app_rpt. (may be valid for other distros ?)

Using the Parallel port for radio COS / PTT is the cheapest and easiest route to go unless you want to hack-up a USB sound dongle that we will not talk about here. If you wish to do that see this link / PDF.

When using parallel port pins for any logic connections most especially experimental ones, I always suggest using something to buffer the lines in the printer/parallel port so that you do not do more damage than to just the port of your PC if higher voltage gets to one of the pins.

Parallel Port Breakout card with Opto-Coupled Transisters on output.

Parallel Port Breakout card with Opto-Coupled Transisters on output.

When I had built a DOS box repeater in the 90’s, I used a opto-coupled transistors to isolate the pins. Now-A-Days you can save yourself a bunch of time and money by buying parallel port cards already made with opto-couplers for cnc driving/controlling on eBay for $30 or less. They even have screw terminals for easy wiring ! The benefit I had back then is I could change the Parallel port card if I damaged it. Now they are built-in. Easy to damage more than just the port.

Just some “experience” talking here. And you know our moto definition of that word ( or see our home page )





First, you need to include a line like this for your  node in RPT.CONF :

iobase = 0x378      ; Parallel port address (using for cor/ptt & switches +dh-rbi )

The address is the parallel port address in hex. Normally 378, 278, 3bc are common addresses for the 1st, 2nd and 3rd ports.

OH… for those that do not know…

PTT is for “push to talk”. A TX line that normally goes to ground when active but not all are like this.

COS/COR is “carrier operated signal” or “carrier operated relay”. The logic on this line varies widely depending on where you can get the signal in the receiver. If your radio has a “s-meter”, that would be a good area to find a appropriate signal.

A short description of the pins we use on a parallel port.

We have:

8 data output lines starting with pin 2 as output 1 (pp1) to pin 9 as output 8 (pp8). These can be used for PTT on multiple nodes as defined in usbradio.conf . I would suggest starting from Output 8 (pin 9 / pp9) and work backwards to reserve the first three for a DH-RBI-1 or future devices. You can also use these to control other devices using relays (out of scope with this page).

5 data input lines  Pins 10,11,12,13 & 15 can be used for COS detections across multiple nodes. You can also use these from other sensors to trigger events in software (off topic, not going there in this page).

Changing the logic in/out with the software:

Parallel Port pins are defined in app_rpt software as “pp1”, “pp2”, “pp3″…etc

Setting them in USBRADIO.CONF


; carrierfrom=no      ;  available options for COS/COR type – Uncomment what’s needed.
; carrierfrom=dsp              ; use a valid signal decoded in DSP (internal)
; carrierfrom=pp                ; states we use pp for COS w/normal logic
carrierfrom=ppinvert     ; this option inverts the logic for cor on the chosen pp
; carrierfrom=usb              ; for hacking usb dongle method
; carrierfrom=usbinvert  ; same as above but inverted
; carrierfrom=vox              ; use vox for COS ( useful for a HF remote base )


txtoctype=notone    ; Transmit tone control type: no,phase,notone
; no – CTCSS tone encoding with no hang time
; phase – encode CTCSS and reverse phase  AKA (“reverse burst”) before unkeying TX
; notone – encode CTCSS and stop sending tone before unkeying TX  AKA (“chicken burst”)

plfilter=yes      ; Filter PL tones/don’t pass to transmitter

invertptt=0     ; use this to invert the normal logic state of the line

#includeifexists custom/usbradio.conf

Some important notes:

The example above is a no-tone with carrier signal (COS) inverted. A simple set-up.

If you lack the ability to set-up a COS circuit, your best option is to set cos as tone/dsp and use that tone to signal a active receiver. Yes that makes your machine a PL’d repeater that you can not turn off the tone. But perhaps it will get you up and running for now.

You may need to invert the logic of pins manually with hardware/transistor to prevent transmitter “key-up” while booting your asterisk machine or it is powered off in certain circumstances where that initial transmitter hang would be disruptive until you get it turned on or booted.

As parallel port outputs (from PC) will only sink about 150 -250 ma of current and about 250-450 ma if you are using the opto-coupled board, you may need to use the line to toggle a external transistor or relay to achieve higher currents to switch the PTT or other devices. If in doubt, use a low current fast relay or transistor to buffer the signal. Save your port and/or machine.