How to set up a NOS-ABS Beacon Server
What do you need to get started? I am
assuming a Linux OS, the ability to edit shell scripts, having Perl
onboard, and a familiarity with cron. That's it! If you can manage all
of the above, you can set up the broadcast side of an ABS in an
afternoon...
- Composing Your Beacon Files
-
The first step is to compose your beacon text
messages. Let's begin with a very simple one-liner! The text below lives in
a file named shortform. I am using the term "form" to imply that this could
be more involved and potentially be a form to be filled in.
|
Example bctext file: /jnos/scripts/beacons/shortform
|
JNOS/Linux 1.11f * Network 105 * 14.105<>145.090 [Wellesley, MA]
|
Note too, that this beacon file is located in the directory
/jnos/scripts/beacons. (You could choose another location if you like.) On
my system, I have placed all beacon/id text files in this directory. And
the content here is minimal, just enough to let the net know that you are
up, what frequencies can be crossed over, and the geographic location. This
is the "classic" one-liner beacon/id.
Let's look at another example beacon text, longform. A bit more information
has been included that may be "interesting" or useful to the net.
|
Example bctext file: /jnos/scripts/beacons/longform
|
KA1FSB-7/Node WELLS * Network 105 * 14.105<>145.090 - Karl
JNOS/Linux 1.11f - TCP/IP 44.56.26.11 - AX25 Utilities
FN42jh - [Wellesley, MA]
|
And, it should be pointed out that this file is a plain "flat" file created
in an editor, such as vi, and is still the "finished" product with no
extra processing being called for. What you see is what you get, just as
you typed it in!
Let's look at a more "interesting" example, a file that is really a
format in Perl. It is called infoform, on my system.
|
Example bctext file: /jnos/scripts/beacons/infoform
|
KA1FSB-7/N (WELLS) * Network 105 * FN42jh [Wellesley, MA]
Local Time.:@>>>>>>>> UTC......:@>>>>>>>>
$loctime, $utctime
Local WX...: @<<<<<<<<<<<<<<<<<<< Temp.....: @<<<<<<<<<<
$wxdesc, $wxtemp
Watches....: @<<<<<<<<<<<<<<<<< Warnings.: @<<<<<<<<<<<<
$wxwat, $wxwarn
|
This "strange" looking file is really a boilerplate or template form that will
be filled in according to the values in the variables below each line. So,
for example, the variable $loctime will be "slugged" into the first field in
its above line. The variable $utctime will be located in the next field, and
so on. The variables list must be comma separated and there must be a variable
for each field in its above line. The "@" character indicates that this is
the beginning of a field to be filled. The "<" and ">" characters indicate
the justification and their number, the actual size of the field. (There is a
bit more to the format keyword in Perl, a declaration and a trailing dot, but
this is all I have placed in the file itself here... )
There is a companion data file to this format file named infoform.var. This
file is optional, but is required if the format file has any reference to
those variables! At some point these variables need to be loaded with
values. A typical variables file for the weather data might look something
like this:
|
Example bctext file: /jnos/scripts/beacons/infoform.var
|
$wxdesc = "Clear & Sunny";
$wxtemp = "Mid 70's";
$wxwat = "(none)";
$wxwarn = "(none)";
|
If this file exists, the program myformer.plx reads in this data and
merges it into the format form. You might be wondering what happened to the
time related variables. Why aren't they included in the companion variables
file? Well, they are built on-the-fly by the Perl program since you want the
latest "live" time on the system. What about the weather data? As it stands
now, an operator has to fill this in. (However, another program dedicated
to this variables file, infoform.var, could update these values from various
machine sources, i.e., the internet or other shared data outputs. That is
why I chose to separate the format files from the variables files.)
So, to review, the format file only needs to be "designed" once. When you
are happy with the appearance, then you can "stuff" it away and not fuss
with it anymore. The variables files were designed to either be completely
over-written or edited manually, or edited by an automated process on
your machine. In other words, an independent listing of data.
To see how this all "comes together," take a look at the next section for the
actual Perl code, myformer.plx.
- Joining Formats & Data: myformer.plx
-
This piece of Perl code is really a very primitive
server. It can accept inputs from the command line via a named pipe, or from
another piece of code, in this case a shell script run from cron. This dual
input function is what makes this code interruptible. At nearly any time,
an operator can issue a special alert or bulletin via a beacon/id
transmission.
|
A Beaconing Server: /jnos/scripts/myformer.plx
|
#! /usr/bin/perl -w
# myformer.plx
# 08-30-04, 08-31-04
# 09-02-04
# KA1FSB/kbn
#
# --------------------------------------------------------------------
# A Merging Server:
#
# Feed in data thru a pipe, now mybeacon. Then get the name of
# the form that was passed in. Process that form and write to
# an output file...
#
# Check to see if any "companion" data files which can be changed
# manually or on-the-fly, or by another program. <beacon-type>.var
#
# If "silent" screen output, use myformer.plx & > /dev/null and
# remove the "-w" at the top of this Perl script...
#
# You may edit or change any .var file on-the-fly. Use this command
# echo "<beacon_name> <device>" > mybeacon to feed the server. Then
# from the JNOS console give that device a kick. ax25 bc <device>
# --------------------------------------------------------------------
#----- Data Inits...
$myPath = "";
$beacon = "";
$loctime = "";
$utctime = "";
$thisform = "";
$myvars = "";
$vars = "";
$device = "";
$line = "";
#----- Default inits...
$myPath = "/jnos/scripts";
$myPipe = $myPath . "/mybeacon";
$myBeacs = $myPath . "/beacons/";
#===== Main
#----- Endless loop...
OUTER: while ( 1 )
{
#----- Open a pipe read here and wait...
open(MYPIPE, "< $myPipe");
$beacon = "";
$device = "";
$line = "";
#----- Should wait here for valid data...
while (defined($line = <MYPIPE>)) {last;}
chomp($line);
$line =~ tr/ / /;
($beacon, $device) = split(/ /, $line);
#----- Release the pipe here...
close(MYPIPE);
#----- Test for a "forced" exit
if ( $line eq "quit" )
{
last OUTER;
}
#----- Make this an upper case format name...
$ucformat = $beacon;
$ucformat =~ tr/[a-z]/[A-Z]/;
#----- File I/O ops, read in data from format form
open(BEACON, "< $myBeacs$beacon");
#----- Begin to build the format
$thisform = "";
$thisform = "format " . $ucformat . " =\n";
#----- Read in the lines... create one big line
while (defined($buffer = <BEACON>))
{
$thisform .= $buffer;
}
close(BEACON);
#----- Requires a "dot" at the end of string...
$thisform .= ".";
#----- Now eval this for any vars...
eval $thisform;
#----- Give the "handle" a name...
*DATAFORM = $ucformat;
#----- NOTE: Open the form for output...
#----- /jnos/scripts/beacons/dataform
open(DATAFORM, "> $myPath/beacons/dataform");
#----- Load a few default Common Global vars...
chomp($loctime = `/bin/date +%H:%M:%S`);
chomp($utctime = `/bin/date -u +%H:%M:%S`);
#----- Load companion variables if they exist, a .var file ...
$vars = $beacon . ".var";
$myBPath = "$myBeacs$vars";
if ( open(VARDATA, "< $myBPath") )
{
while (defined($line = <VARDATA>))
{
chomp($line);
$myvars .= $line;
}
close(VARDATA);
eval $myvars;
}
#----- Write the format block ...
write (DATAFORM);
#----- Close the file
close(DATAFORM);
#----- Now build the JNOS do_beacon script,
#----- "dataform" is the repository for all the formats above, etc...
system("/jnos/scripts/build_beacon $device dataform");
}
#----- "Offical" exit on quit
exit;
#----- End of myformer.plx
|
My location for this code is in /jnos/scripts. You could locate it anywhere
as long as you use full path names for the input and output files. You also
need to create a named pipe. I called mine mybeacon, but you may call it any
name that makes sense to you, just be sure the Perl code agrees with any
name changes you make. Here is how to create the pipe, and it should be
located in /jnos/scripts, or where ever you decide to locate the code. (In
other words, all these items should be together... )
This pipe now serves as the input to the server. It should be created with
root ownership granting write permission to root only.
To start up the server, after logging in as root, use this command from
the prompt:
- myformer.plx > /dev/null &
The /dev/null will catch many of the "warnings" coming from Perl or from
the system. You may also remove the "-w" from the topmost line in the script
after you see it is working OK. (Sometimes, Perl likes to "comment" on the
activities of eval.)
To "talk to" the server from the prompt, use this line:
Where mybeacon is the named pipe which is the input for the Perl code,
myformer.plx. This command will stop the server. To pass a processing
command into the (pipe) server input, use:
- echo "infoform hf" > mybeacon
This tells the server to get the format and variable files for infoform which
will be set up on the hf device. Note, too, that all output data is written
to a file /jnos/scripts/beacons/dataform. This is essentially the output
"buffer." The final step is a call to build_beacon which takes the content
of dataform as its input and continues to generate the JNOS script file,
do_beacon. That script will in turn be called by one of the AT timer
routines, loading the ifconfig table for device hf, and finally will
be sent out as the next beacon message...
Remember, you may pass in the name of any format form that you have created
that resides in /jnos/scripts/beacons at any time. This affords great
flexibility. If you interrupt the regular broadcasts, or interject with
a special alert, it will return to the normal cycle according to the
schedule that you have set up in a broadcast table.
- Automating the Feed to myformer.plx
-
As seen above one way to "talk to" the myformer.plx
server is to echo commands in from the keyboard. But eminently more useful is
the ability to feed a command line from another program or script. This is
where the shell script do_sched comes into play. This script reads a table
for the broadcast schedule and then sends a command line to the server, just
as if it had been typed in by hand. Here is the code:
|
Shell Script: do_sched
|
#! /bin/sh
# do_sched
# KA1FSB/kbn
# 08-28-04, 08-30-04 (bambi)
# 09-02-04
#
# ---------------------------------------------------------------------
# Lookup in sched table what is to be run at what time and
# compare to time now. Then send down the pipe the correct commands
# to the server which are in the table...
#
# First, check to see if pipe exists. And check if server is running.
#
# Should be run only once for each call from cron.
# Can accept command line argument for the lookup table from cron
# ---------------------------------------------------------------------
#----- Inits...
line=""
Minutes=""
tblMins=""
myPipe=""
myProg=""
myForm=""
myTable=""
device=""
ISUP=""
#----- Data Inits...
myPath="/jnos/scripts/"
#----- Defaults or pass in...
if [ "$1" ]
then
myTable="$1"
else
myTable="sched.tbl"
fi
#===== Main
#----- Get the minutes from the system clock...
Minutes=`date +%M`
#----- Main process loop, read table file for data...
#----- Break out if table minutes greater/equal than system time minutes
while [ 1 ]
do
read tblMins myForm myProg myPipe device || break
test `echo $tblMins | grep ^#` && continue
if [ $tblMins -ge $Minutes ]
then
# echo "Sending this to $myPipe: $myForm $myProg for $device"
break
fi
done < ${myPath}${myTable}
#----- Is pipe there ?
if [ ! -e "${myPath}${myPipe}" ] && [ ! -p "${myPath}${myPipe}" ]
then
echo "The file $myPipe is not a pipe! Server needs this pipe"
exit
fi
#----- Is program running?
ISUP=`/bin/ps ax | /usr/bin/grep ${myProg} | /usr/bin/grep -v grep`
if [ ! "${ISUP}" ]
then
echo "The program $myProg is not running now ... exiting"
exit
fi
#----- Then send command line args to server on this pipe only if
#----- all of the above conditions are true ...
echo "$myForm $device" > ${myPath}${myPipe}
exit
#----- End of do_sched
|
Again, this piece of code needs to be in the same directory as all the others
mentioned here. I use /jnos/scripts, but as long as you are consistent, you
may locate it anywhere you like.
Aside from looking up data in a table, this script checks to see if a named
pipe exists and if its receiving server is up and running. There is nothing
worse than trying to send to a non-existent pipe or server. So, it won't
try unless it finds everything is a "go." A little bit of defensive
programming...
Here is the cron line that you need to enter to coordinate this script with
the broadcast schedule. (Use crontab -e to enter this line.)
- 18,38,58 */1 * * * /jnos/scripts/do_sched sched.tbl 1>/dev/null 2>/dev/null
These times are set for a 20 minute cycle through the hour. (The shell script
will be run at 18, 38, and 58 minutes after every hour.) To find out more
about automating and synchronizing beacons: please see,
Automating a Beacon and
Synchronzing a Beacon for
details.
|
The Schedule Table: sched.tbl
|
#Time Form Server Pipe device
20 shortform myformer.plx mybeacon hf
40 infoform myformer.plx mybeacon hf
60 longform myformer.plx mybeacon hf
|
The table lists all the needed data to automatically construct a wide
variety of beacons! Even though this setup might seem like a lot of
"overhead," it allows for great flexibility. The code do_sched may take a
different table name as its argument, and the detailed data in any given
table, may refer to a wide range of options, i.e., named pipes, format
forms, and servers that may all be running. These methods are quite
re-useable...
And this table can be edited on-the-fly as well. If a line begins with the
pound sign "#", it will not be seen by the shell script. This makes it easy
to have alternate lines which can be switched in quickly with just a few
key strokes.
|
The Schedule Table: sched.tbl with alternate lines commented in/out
|
#Time Form Server Pipe device
20 shortform myformer.plx mybeacon hf
40 infoform myformer.plx mybeacon hf
#40 shortform myformer.plx mybeacon hf
60 longform myformer.plx mybeacon hf
#60 shortform myformer.plx mybeacon hf
|
I often set all the lines to broadcast the shortform unless there is
something worth sending out as a public announcement, like a severe
storm warning, or a unusually "nice" day for my part of the world. :)
- Interjecting an Alert or Emergency Beacon
-
Suppose you have a beacon message that you want to
broadcast immediately. And further suppose that this message has been
completed, resides in /jnos/scripts/beacons, and is ready to go. There are
three (3) steps/commands to accomplish this transmission:
- From Linux: echo "<beacon_name> <device>" > mybeacon
- From JNOS: source /jnos/scripts/do_beacon
- From JNOS: ax25 bc <device>
The first step should be taken from /jnos/scripts or wherever you have located
all the server support code. And since the automated part of the server is
still in force, you might want to be sure you are not conflicting with a
previously scheduled broadcast. (If you are quick, you can probably send out
the alert in less than a minute.) So the output of your alert message will
appear in /jnos/scripts/do_beacon almost immediately. (You can check to be
sure ... )
Step two requires that you change to the JNOS console, either logging in as
sysop or switching sessions, and run the JNOS script do_beacon. This loads
the ifconfig table with the new message.
The last step "fires" the beacon out onto the net. Since this is an
"interjection," all regularly scheduled broadcasts will resume as usual.
- Caveats
-
As always, you copy, use, and modify this code at
your own risk. As we all know, code running on one system may not always
adapt well to other systems or packages. So, for a start, please be sure
to read as much as you can "tolerate" in the NOS-ABS index page. These
"utilities" have been running fine here for about two (2) months now with
no "detectable" problems. That doesn't mean there aren't any. The code is
in a perpetual prototypical state and is easily modifiable by you, the user,
net sysop, or programmer. (That is the good part!)
- Concluding Observations ...
-
So here is a summary list of the required
components for a NOS-ABS Beacon Server:
- A Named Pipe: mybeacon
- A Shell Script: do_sched
- A Cron entry for do_sched
- A Perl Server: myformer.plx
- A Perl Script: build_beacon
- A Schedule Table: sched.tbl
- A Directory under /jnos/scripts: /beacons
- A Selection of Beacon Text Messages
- A JNOS Script such as: do_beacon built by build_beacon
By coordinating these code and system "parts," you can gain complete mastery
of the JNOS broadcast system! You can send out nearly any kind of information
you wish, in any format, and at any time. If you are a programmer, or have
been a Linux administrator for some time, take a look at these ideas and
build your own system around the concepts. These programs all work fine,
but the design I chose is one that can be extensively modified to fit your
network. Have fun and keep experimenting with the "NOS-ABS utilities!"
You never know what you might come up with!
For more background and supplemental information, please see
Automating a Beacon for
the comprehensive treatment of this topic.
(Courtesy KBNorton Computer Services)
|