app_rpt__ultra was designed to be the ultimate controller experience for Asterisk AllStarLink app_rpt! Built on the history and capabilities of standalone repeater controllers from the 1980s-2000s, this platform was designed to combine the art and technology of today with yesteryear. Some of the features included were takeaways and inspirations from controllers similar to Advanced Computer Controls, Link Communications, Computer Automation Technology and FF Systems.
All of the frameworks were written in Bash (Bourne again shell) using scripts that are called by app_rpt. The intent was to modify as little as possible so frameworks were relatively immutable and could survive any code updates to Asterisk and app_rpt. Most scripts are called either from within Asterisk or from local cron jobs.
- Management of repeater states or personalities;
- Rotating identifier and tail messages;
- An advanced message editor with the ability to program messages, courtesy tones and telemetry via DTMF;
- A vocabulary of 877 words and sound effects with dozens of pre-defined phrases1;
- Weather alerting system, powered by NOAA NWS alerts;
- Reporting weather conditions, powered by Weather Underground2;
- Full integration with Asterisk AllStarLink app_rpt without any code modification!
Warning
Only AllStarLink 3 is supported; functionality for previous versions of app_rpt have been removed.
mkdir -p /usr/src
cd /usr/src
git clone https://github.com/AI3I/app_rpt__ultra.git
cd app_rpt__ultra
mkdir -p /opt/app_rpt /opt/asterisk /etc/asterisk/custom
rm -rf /var/lib/asterisk/sounds /usr/share/asterisk/sounds
cp -Rf app_rpt/sounds/* /opt/app_rpt/sounds/
cp -Rf app_rpt/bin/* /opt/app_rpt/bin/
ln -s /opt/app_rpt/sounds /var/lib/asterisk/sounds
ln -s /opt/app_rpt/sounds /usr/share/asterisk/sounds
You will need jq, a JSON parser, for successful execution of all scripts within the suite.
apt install jq -y
app_rpt__ultra will require required unfettered use of Asterisk's native local account, asterisk, and requires an interactive shell with sudo access.
usermod -s /bin/bash -G sudo,dialout,audio,plugdev asterisk
Caution
The dialout, audio, and plugdev groups are important for stable operation in ASL3. Should you remove access to those groups, USB audio and control interfaces running under the asterisk account will not work!
Modify /etc/sudoers to ensure NOPASSWD is added to the sudo rule:
# Allow members of group sudo to execute any command without a password
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
chmod -Rf asterisk:asterisk /etc/asterisk /opt/asterisk /opt/app_rpt /usr/src/app_rpt__ultra
sudo su - asterisk
crontab -e
Use the following for your crontab:
# apt_rpt__ultra crontab
0 0 * * * /opt/app_rpt/bin/datekeeper.sh # Produce today's date for readback
0 0 * * * /opt/app_rpt/bin/datadumper.sh # Purge old recordings
*/15 * * * * /opt/app_rpt/bin/weatherkeeper.sh # Produce current weather conditions
* * * * * /opt/app_rpt/bin/timekeeper.sh # Produce the current time for readback
* * * * * /opt/app_rpt/bin/idkeeper.sh # Manage all system IDs
* * * * * /opt/app_rpt/bin/tailkeeper.sh # Manage all tail messages
* * * * * /opt/app_rpt/bin/weatheralert.sh # Poll for (severe) weather alerts
Tip
- Replace
%MYNODE%
to match your AllStarLink node number (we used 1999 as an example) - Replace all instances of
%MYCALL%
within the file with your call sign (we used MYC4LL as an example) - Be sure to check your duplex and rxchannel values to ensure they align with desired operation (i.e. with usbradio.conf or simpleusb.conf)
- Do not change the idrecording=voice_id parameter in rpt.conf; this is overwritten by idkeeper.sh, which you will learn more about later. Copy configuration templates:
cp asterisk/rpt.conf /etc/asterisk/rpt.conf
cp asterisk/extensions_custom.conf /etc/asterisk/custom/extensions_custom.conf
cp config.ini /opt/app_rpt/config.ini
In order to start with the basics, you can do a sed replacement:
sed -i s/%MYNODE%/1999/g /etc/asterisk/rpt.conf
sed -i s/%MYCALL%/MYC4LL/g /etc/asterisk/rpt.conf
sed -i s/%MYNODE%/1999/g /opt/app_rpt/config.ini
Let us assume our voice ID will say "This is M Y C 4 L L repeater." We can achieve this by concatenating several files together to produce our ID, as follows:
cd /opt/app_rpt/sounds/_male
cat this_is.ulaw m.ulaw y.ulaw c.ulaw 4.ulaw l.ulaw l.ulaw repeater.ulaw \
> /opt/app_rpt/sounds/voice_id.ulaw
The message is written and can be tested through manual invocation by using:
sudo asterisk -rx "rpt localplay 1999 voice_id"
sudo chown -Rf asterisk:asterisk /etc/asterisk /opt/app_rpt /opt/asterisk
sudo su - asterisk
/opt/app_rpt/bin/datekeeper.sh
sudo systemctl restart asterisk
Now that you've set up the basics and have legal IDs, it's time to dive deeper into the general operation and behavior of app_rpt__ultra. You have configured cron jobs that are now managing general operations of your system, and by periodically dispatching scripts to do our bidding.
Note
All scripts reference /opt/app_rpt/config.ini for both runtime and master configuration data. Should you make any edits to scripts within /opt/app_rpt/bin, please be cognizant of any changes that may need to be carried over to config.ini accordingly!
This script basically the magic and the heart of it all. The purpose of statekeeper.sh is to manage all of your system's personalities, or states, and effectively do so on demand or when conditions are met.
States can be invoked in any number of ways:
- through the command line;
- through the internal scheduler;
- or using DTMF commands.
Several states, or personalities, have been pre-programmed to suit your general day-to-day needs:
State Name | Purpose | Behaviors |
---|---|---|
default | Default Mode | This is the default power-up state that generally cleans up any modifications from other states, and puts your system back to a pre-defined running state. This reads values set to default in config.ini and performs a number of sed replacements, and reloads Asterisk. |
standard | Standard Mode | This is an alternate to the default power-up state and an ideal area for a general static operating state, especially if you don't intend to leverage daytime or nighttime modes with the scheduler. |
daytime | Daytime Mode | Fit for daytime operations, this is a great place to set all of your behaviors when both system users and control operators are somewhat attentive. |
nighttime | Nighttime Mode | This scenario is ideal for locking a few things down, adjusting timers, and preparing your system for nighttime operations when the repeater is largely unattended. |
net | Net Mode | This adds a lot of brevity, changes courtesy tones, relaxes a few timers, and suppresses telemetry and messaging. |
tactical | Tactical Mode | Similar to net mode, but ideal for tactical operations with adjusted timers and a distinct courtesy tone. |
weatheralert | Weather Alert | This announces "weather alert" as a tail message, relaxes timers, but maintains normal operations. |
severeweather | Severe Weather Mode | This changes the courtesy tone, announces "severe weather alert" for a tail message with aggressive timing, suppresses time-out timers, and sends a two-tone page alerting of severe weather. |
stealth | Stealth Mode | With the exception of required CW ID, this suppresses all telemetry including voice synthesis, courtesy tones, eliminates hang/tail timers, and disables the scheduler. |
litzalert | Long Tone Zero (LiTZ) Alert | This generates two-tone pages and announcements when the LiTZ command is executed to garner the attention of control operators who may lend assistance. |
clock | Grandfather Clock | This emulates the CAT-1000 grandfather clock and can be called through the scheduler at the top of every hour. |
This script makes calls into Asterisk to determine current repeater and identifier states, and based upon config.ini and pre-defined behaviors in statekeeper.sh will determine what identifiers it plays, and when.
Variables | Values | Description & Behaviors (config.ini) |
---|---|---|
SPECIALID | 0 or 1 (boolean) | Override all IDs with the Special ID? |
ROTATEIIDS | 0 or 1 (boolean) | Whether Initial IDs are rotated or not? |
ROTATEPIDS | 0 or 1 (boolean) | Whether Pending IDs are rotated or not? |
INITIALID | { 1 .. 3 } (fixed range integer) | Selection of a specific Initial ID. |
PENDINGID | { 1 .. 5 } (fixed range integer) | Selection of a specific Pending ID. |
This follows statekeeper.sh behavior and adjusts tail messages based upon operational condition and weather conditions. By default, it will rotate in messages for current time and local temperature, if Weather Underground is configured.
Variables | Values | Description & Behaviors (config.ini) |
---|---|---|
ENABLETAIL | 0 or 1 (boolean) | Whether the tail messages are enabled or not? |
ENABLETIME | 0 or 1 (boolean) | Whether periodic time announcements are given in tail messages or not? |
ENABLETEMP | 0 or 1 (boolean) | Whether periodic temperature readings are given in tail messages or not?2 |
ROTATETMSG | 0 or 1 (boolean) | Whether to rotate tail messages or not? |
TAILMSG | { 1 .. 9 } (fixed range integer) | Selection of a specific tail message. |
This monitors NOAA National Weather Service alerts, if configured for your NWS zone, and will trigger statekeeper.sh to change to a weather alert or severe weather alert, if enabled.
Variables | Values | Description & Behaviors (config.ini) |
---|---|---|
NWSZONE | XXX000 | The default value is invalid and should be replaced with your local NWS zone. NWS Public Forecast Zones |
NWSFILE | /opt/app_rpt/lib/nwsalerts.out | Explicit file path where weather alerting data is kept for parsing by jq. |
SEVEREWEATHER | { 0 .. 3 } (fixed range integer) | 0: disables the feature 1: indicates a severe weather alert 2: indicates a weather alert 3: deactivated; conditions are normal |
RTWXALERT | tails/weather_alert | Relative file path of tail message to be played for routine weather alert. |
SVWXALERT | tails/severe_weather_alert | Relative file path of tail message to be played for severe weather alert. |
This polls Weather Underground2 to poll for weather station data in your region. Several conditions, such as temperature, humdity, wind speed and direction, et al., are generated which can be called by invocation.
Variables | Values | Description & Behaviors (config.ini) |
---|---|---|
FETCHLOCAL | 0 or 1 (boolean) | Whether to pull data from a local system (i.e. hub system that collates your weather data). The default is 0. |
WUAPIKEY | empty | Should be populated with your Weather Underground API key.2 |
WUSTATION | empty | ID of a Weather Underground station that provides you with local weather data.2 |
WUOUTPUT | /opt/app_rpt/lib/wunderground.out | Explicit file path where raw JSON data is kept for parsing by jq. |
This purges old recordings after they have aged by the defined period in the script.
Variables | Values | Description & Behaviors (config.ini) |
---|---|---|
RETENTION | integer | The number of days to keep recordings. The default is 60 days and recordings are stored in /opt/asterisk with status logs. |
This generates date messages once daily for playback by invocation.
There are no configurable options.
This generates time messages every minute for playback either in tail messages or by invocation.
There are no configurable options.
Footnotes
-
These are high fidelity recordings from a Texas Instruments TSP5220 speech synthesizer, sourced from an Advanced Computer Controls (ACC) RC-850 controller, version 3.8 (late serial number). ↩
-
Weather reporting requires account registration and use of an API key from Weather Underground. ↩ ↩2 ↩3 ↩4 ↩5