Automating a Beacon in JNOS


Or, how to set up an Automatic Beaconing System...

What is an automated beacon; and why do you think you might want one? An automated beacon system generates, or refreshes, beacon broadcast messages on a regular basis just as a normal beacon system does except it can modify its content on-the-fly, or accept special interuption alerts and then re-sync back to its normally scheduled broadcasts! The most familiar example would be an APRS system which relies heavily on beacon broadcasts to "announce" a station's Lat/Lon position. If the station is mobile, then the beacon broadcast becomes refreshed with new position information. If you are a user or devotee of APRS, then this is an almost painfully obvious observation. However, if you are in the *NOS group, and sometimes look with "envy" at APRS capability, it may not have occurred to you that you too can use beacons to very similiar ends! :)

Why might you want to do this? Aside from the previous mobile example, dangerous weather, flood, or fire conditions come to mind. In other words, the prevention of disaster, due to unpredictable events in nature, might be minimized or averted by providing adequate warning to those actually in harm's way, or to the agencies that are well-equipted to handle such emergencies. (I am sure you can think of many compelling reasons for employing automated beacon systems, especially if you are tooling up or re-tooling your station for emergency operations, or if you are actively involved in ARES or RACES organizations...)




Setting up an Auto-Beacon System

What software components do you need to begin? You need Perl and a very basic understanding of how to edit code. You need to have the "at" facility in JNOS enabled and the ID, or beaconing system, active which in 99.9% of the distributions, is already there. You need to have cron running on your Linux machine as well, again this is usually there right out of the box. That's it! (If you are a programmer, you can use any language you like that is adept at text/string handling. My examples will be in Perl, but they should be straighforward enough so that you can translate them into your favorite code if you want...)

Here is my synchronous strategy for the solution to the auto-beacon problem. Use a Perl script to read a file which has the plain text part of the broadcast message, and update or swap-in any dynamic components if required. Use a Perl script to build and format a JNOS type script, which resides in /jnos/scripts/, named do_beacon, so named here for purposes of illustration. (You could call it anything you like...) Use the AT facility in JNOS to run do_beacon at regular intervals. So, for example, cron could be scheduled to run at perhaps a few minutes after the top of the hour. The JNOS AT script could run a few minutes later, and finally the BEACON/ID would be broadcast a few minutes later still, at perhaps 20 after the hour.

COMMENTARY : It should be noted that this approach is a highly synchronous one, and that other, less "strict," more asynchronous approaches to this class of problem could be applied. There is room for both synchronous and asynchronous types of information broadcasts on the net. Each has its own application niche. I chose the "road less travelled" since I wanted to show the potential system "links" between JNOS and Linux, and the areas that might show developmental promise. You may choose more straightforward methods which will work just as well...



Continuing on, if there were no change to the above text message, then the do_beacon script would simply be "re-freshed" and re-broadcast as usual. If new data were inserted into the message then that is what would be sent out. If a special message were created manually by you, and sent out between the regular intervals, then after its transmission, the normal broadcast could be restored to its orginal format and sent as usual via cron, do_beacon, and the "at" command. A very flexible system that is remarkably reliable since it is built on system components that are proven and stable!

The Most Simple Case

Let's begin with the easiest "model" to follow first. Suppose we don't want to change our beacon, but we just want to put into place the foundation which potentially could change it. We need to take two steps.

  • Build the do_beacon file
  • Set a time(s) for the AT facility in JNOS

In the directory /jnos/scripts, create a JNOS script that loads the configuration buffer for the target device with the actual message to be broadcast, which needs to be in quotes and optionally end with the "\r" carriage return character. Recall too, this is a JNOS script, not a shell script, so it doesn't need to be chmod'ed with the +x switch. (It is just a regular flat text file.) JNOS knows to activate it because it resides in the directory /jnos/scripts.

Sample Beacon Script: /jnos/scripts/do_beacon
# JNOS script
# do_beacon
# 07-25-04
# KA1FSB/kbn
# -------------------------------------------------------------
# Loads device beacon text buffer via ifconfig command
# Possible beacon kick at this time ...
# This is for device/iface hf
# -------------------------------------------------------------
#
ifc hf ax25 bctext "JNOS/Linux 1.11f * Network 105 * 14.105<>145.090 
 [Wellelesy, MA]\r"
#
# Optional beacon kick here...
# ax25 bc hf
#
#----- End of do_beacon
For easier viewing, I have placed the station location on a new line (\n). In the real file, this would all be one massive line, sometimes extending "far" to the right even off the screen! If we had multiple lines, each one would be terminated with the "\r" only, and would be representated as one continuous string in the file! Also, the first command, ifc, is not commented out and so will be applied; the second, ax25 bc hf, is commented out and so will not be applied, but could be if uncommented...

The second step is to tell JNOS when you want to run this script. For that, you may use the AT command. AT is a timer facility that runs JNOS functions or scripts, which may contain multiple commands as in the above example, at a specified time or times. A typical command issued form the console/admin session looks like this:

  • at 05 "source /jnos/scripts/do_beacon+"


The plus sign "+" at the end of the command line means do this again in the time interval shown, i.e., 5 minutes after each hour. Entering "at" from the admin console will display the entry in the JNOS AT event table:

A Typical AT Command Table Entry

At: Mon Aug  2 09:05:08 2004 - ID:     1 - Command: source /jnos/scripts/do_beacon+

And, there is no reason why you can't run the same script at several pre-set intervals:

  • at 15 "source /jnos/scripts/do_beacon+"
  • at 30 "source /jnos/scripts/do_beacon+"
  • at 45 "source /jnos/scripts/do_beacon+"
  • at 59 "source /jnos/scripts/do_beacon+"


This will run the script at 15, 30, 45, and 59 minutes after every hour! (You could run do_beacon even more often if the situation required. More likely, you would not need to do so under normal conditions...) Also, you could choose not to use the traditional beacon timer and use this instead, but this script, as written, only updates the beacon area. It does not actually do a beacon TX, although it could. (Perhaps, best to let the global beacon timer handle the actual transmissions at this point.)

Auto-Building the do_beacon JNOS Script

We are now ready to take this process to the next "level," a place where it gets "interesting," but is still fun! To build the do_beacon script, we need a template file and a Perl script. Here is what the template file looks like:

Sample Beacon Template file: /jnos/scripts/do_beacon.tmplt
# JNOS script
# do_beacon
# 07-25-04
# KA1FSB/kbn
# -----------------------------------------------------------------
# Generated on: MYDATE by build_beacon  
# JNOS script to load the device configuration buffer for bc text  
# -----------------------------------------------------------------
#
ifc DEVICE ax25 bctext "BODY"
#
# ax25 bc DEVICE
#
#----- End of do_beacon

Notice the three (3) upper case, bolded, names: MYDATE, DEVICE, and BODY. The Perl script will replace these names with real data! MYDATE will become today's real date; DEVICE will become, in this case, hf; and BODY will become the entire message string for the broadcast text. This template file, do_beacon.tmplt is read by the Perl script, and is then "transformed" into a new copy of the do_beacon JNOS script ready to be executed.

Here is what that Perl script looks like:

Perl Script: build_beacon
#! /usr/bin/perl -w
# build_beacon
# 07-25-04, 07-26-04
# KA1FSB/kbn
#
# --------------------------------------------------------------------
# Script to insert various idents and data lines,
# so that it may be automated and run in background, using "at"
# and cron together... cron would run this one, and "at" would at
# intervals run "source /jnos/scripts/do_beacon"
#
# To get the \r, you need to use \\r, so that the backslash shows up.
#
# Usage: build_beacon <device_type> <beacon_form_type>
#
# NOTE: This will build a beacon kicker for any device; just make sure
# that it exists!
# --------------------------------------------------------------------

#----- Inits...
$buffer = "";
$line   = "";
$date   = "";
$buffer = "";

#----- Defaults...
$beacon = "shortform";
$device = "hf";

#----- Data Inits...
$eol    = "\\r";
$myPath = "/jnos/scripts";

# ----------------------------------------------------------------
# Main process
# ----------------------------------------------------------------

#----- First look for command line args...
$device = $ARGV[0] if $ARGV[0];
$beacon = $ARGV[1] if $ARGV[1];

#----- Clear the previous file "buffer" ...
system("> $myPath/do_beacon");

#----- Get date for today
chomp($date = `/bin/date`);

#----- File I/O ops
open(FI, "< $myPath/do_beacon.tmplt");
open(FO, ">> $myPath/do_beacon");
open(BEACON, "< $myPath/beacons/$beacon");

#----- Read in the lines... create one big line
while (defined($buffer = <BEACON>))
{
        chomp($buffer);
        $line .= $buffer . $eol;
}
close(BEACON);

#----- Now make subs in the template file with real data swapped in...
$buffer = "";
while (defined($buffer = <FI>))
{
        chomp($buffer);

#----- Make replacements...
        $buffer =~ s/MYDATE/$date/;
        $buffer =~ s/BODY/$line/;
        $buffer =~ s/DEVICE/$device/g;

        print FO "$buffer\n";
}

#----- Close all opens...
close(FO);
close(FI);

#----- End of build_beacon

This is a fairly straightforward piece of code. It accepts and requires two (2) command line arguments: the device, hf, and the input beacon text file, here named shortform. The script also captures today's date. It opens the template file and makes the swaps. And, it's done! The output is the updated do_beacon file.

Where does it get the shortform file? Well, there is a directory called beacons, which you create, under the /jnos/scripts direcory. This is where you can keep any and all forms that you wish to use as bctext files. Here is what the shortform file looks like:

Sample shortform file: /jnos/scripts/beacons/shortform
  JNOS/Linux 1.11f * Network 105 * 14.105<>145.090 [Wellesley, MA]

and here is the final output as generated by build_beacon:

Auto-Generated do_beacon JNOS script
# JNOS Script
# do_beacon
# 07-25-04
# KA1FSB/kbn
# ------------------------------------------------------------------
# Generated on: Mon Jul 26 10:37:24 EDT 2004 by build_beacon
# JNOS script to load the device configuration buffer for bc text  
# ------------------------------------------------------------------
#
ifc hf ax25 bctext "JNOS/Linux 1.11f * Network 105 * 14.105<>145.090 
 [Wellelesy, MA]\r"
#
# ax25 bc hf
#
#----- End of do_beacon

To run build_beacon manually, issue this command:

  • build_beacon hf shortform

Where hf is the device name and shortform is the beacon text file. At this point, we have what could be described as a semi-automated system. Depending on how often the AT function has been set to run do_beacon, we only need to run this build_beacon script just prior and with the parameters that we need to have set into the broadcast. For example, you might wish to run another bctext file named longform. This is a slightly more detailed version of the shortform. It is also a plain text file. (You enter it exactly as you wish to see it displayed in the broadcast, "what you see is what you get.")

Sample longform file: /jnos/scripts/beacons/longform
JNOS/Linux 1.11f * Network 105 * 14.105<>145.090 - Karl
    KA1FSB-7/N (WELLS)  -  TCP/IP 44.56.26.11
             FN42jh [Wellesley, MA]

Invoking the command build_beacon hf longform, would produce a do_beacon JNOS script as follows:

Auto-Generated do_beacon JNOS script for longform
# JNOS Script
# do_beacon
# 07-25-04
# KA1FSB/kbn
# ------------------------------------------------------------------
# Generated on: Mon Jul 27 10:37:37 EDT 2004 by build_beacon
# JNOS script to load the device configuration buffer for bc text  
# ------------------------------------------------------------------
#
ifc hf ax25 "JNOS/Linux 1.11f * Network 105 * 14.105<>145.090 - Karl\r
    KA1FSB-7/N (WELLS)  -  TCP/IP 44.56.26.11\r
             FN42jh [Wellesley, MA]\r"
#
# ax25 bc hf
#
#----- End of do_beacon

Again, I have placed "\n" in the file for readabillity here. In the actual do_beacon file, the ifc line would be "off the screen," seen as one very long string. The build_beacon script essentially replaces all '\n' characters in the original text file with '\r' characters in the do_beacon JNOS script, and it surrounds the text body with quotations to satisfy the ifc command syntax.

So, what do we have so far? We have set-up a feeder system using a JNOS script named do_beacon, a template for that script named do_beacon.tmplt, and a Perl script to convert various input flat text broadcast message files into the correct command syntax for the JNOS script facility. And, perhaps we have scheduled AT into action to always run the do_beacon refresher at pre-determined intervals. We can create, on-the-fly, any message file we wish in the beacon directory, and by running build_beacon, we can "merge" that file into do_beacon, which in turn will prepare the device's beacon area for its next scheduled broadcast.

Using Cron to Automate the Linux Side

Can we automate this process even more, and of course, the answer is yes! We can set up a schedule line in cron to run just before our AT do_beacon run. This cron command will run build_beacon on a "fixed" port/device but with a file named anyform. So all we need to do is copy our beacon message, which could pre-exist or be created on-the-fly, into the "feeder" file, anyform. Here is the sequence of commands to set this into "motion:"

From the JNOS console enter:

  • at 15 "source /jnos/scripts/do_beacon+"


which will set up the AT to run at 15 minutes past every hour.

From crontab -e enter:

  • 10 */1 * * * /bin/bash /jnos/scripts/build_beacon hf anyform 1>/dev/null 2>/dev/null


which will set cron to run this script at 10 minutes past every hour.

So, as can be seen, we must synchronize these operations to get the sequencing right. The cron utility runs the build_beacon script at 10 minutes after each hour and the JNOS AT runs do_beacon at 15 minutes past the hour. If we were scheduled to beacon at 20 minutes past every hour, then "in theory" any changes to the do_beacon script would always be updated properly. If we do nothing to the file anyform, located in /jnos/scripts/beacons, then whatever was first copied into it, will be what is broadcast. However, if we edit, change, or copy any other pre-existing message into that file, then that is the one that will beaconed after cron runs build_beacon and AT runs do_beacon at their coordinated times...

And speaking of coordination and synchronization, we need to be absolutely sure that the clocks on JNOS and on Linux are on the same "page" to within a second. Place the following command near the end of your autoexec.nos file:

  • rdate server ka1fsb.ampr.org

(Replace my domain name above with your FQDN for the host machine that is running the JNOS application, or use the IP number for your Linux host machine... rdate will "copy" the time from the Linux host to JNOS.)

And, to synchronize the actual beaconing transmission, please see "Synchronizing a Beacon in JNOS". for a detailed explanantion of this setup.

Suppose we were set to beacon every 20 minutes and we wanted to be sure that each beacon "event" was properly accounted for. We would have to set up an AT schedule very similar to the single-time one shown above. Here is a listing of those JNOS AT commands based on a 20 minute broadcast interval:

  • at 15 "source /jnos/scripts/do_beacon+"
  • at 35 "source /jnos/scripts/do_beacon+"
  • at 55 "source /jnos/scripts/do_beacon+"


And here is the line for cron...

  • 10,30,50 */1 * * * /bin/bash /jnos/scripts/build_beacon hf anyform 1>/dev/null 2>/dev/null

The cron line translates to: run this script each hour at 10, 30 and 50 minutes after each and every hour...

The general rule I am following is: run build_beacon five minutes before do_beacon, and run do_beacon five minutes before actually beaconing. We are beaconing at the top of the hour, 20 minutes after, and 40 minutes after. The allocation of scripting "resources" must be properly sequenced to anticipate any change in the beacon message. If you were to beacon every ten (10) minutes, then the AT JNOS commands would need to be adjusted accordingly, as well as the cron schedule line.

In sum, each beacon transmission is preceded by a call to do_beacon which in turn is preceded by a call to build_beacon. If you were automating position beacons for mobile units, then even more frequent time divisions might be considered. Therefore, it might be a good idea to place all these JNOS AT timers into a single JNOS script! (You could name it something like do_bctimers, and it could also be subject to auto-generation based on the timing differentials... just a thought :)

Automating "the Automaters"

Can we take this one step farther still? And, again, the answer is yes! We can create "forms" on-the-fly that can be "filled in" dynamically from various sources: data from OS calls, such as the time and date function; reading log or data collections files; and even pulling streams from pipes or sockets connected to the internet.

To keep things simple though, the example that will be developed here will present a strategy for managing dynamic data flows. My approach to this problem is to use another Perl script, and use its "format" data structure to create a real, "live" form. Then write the output to a file named dataform in the usual place, /jnos/scripts/beacons, and then call build_beacon with that file as one of its argument. Let's take a look at the Perl script:

A Perl Script for Dynamic Form Building: dataform.plx
#! /usr/bin/perl -w
# dataform.plx 
# 07-27-04, 07-31-04
# KA1FSB/kbn
# ---------------------------------------------------------------
# Sample script for generating a dynamically populated form.
#
# Time is the only trully dynamic datum used here, but other
# types like Lat/Lon, etc, could be gathered and built from here.
#
# The output form is named dataform in /jnos/scripts/beacons
# Although a bit hard-coded, takes advantage of Perl's "format"
# data structure builder.
# ---------------------------------------------------------------

#----- Data Inits...
$wxdesc  = "Sunny w/ some clouds";
$wxtemp  = "70";

$myPath  = "/jnos/scripts/beacons";

$loctime = "";
$utctime = "";


#----- The format as defined by Perl
format DATAFORM =
KA1FSB-7/N (WELLS) * Network 105 * FN42jh  [Wellesley, MA]
   Local Time.:@>>>>>>>>                 UTC..:@>>>>>>>> 
$loctime, $utctime
   Local WX...: @<<<<<<<<<<<<<<<<<<<<<   Temp.:@##
$wxdesc, $wxtemp
.

# -----------------------------------------------------------------
# Main
# -----------------------------------------------------------------

#----- Open the form for output...
open(DATAFORM, ">$myPath/dataform");

chomp($loctime   = `/bin/date +%H:%M:%S`);
chomp($utctime   = `/bin/date -u +%H:%M:%S`);

#----- Write the format block ...
write (DATAFORM);

#----- Close the file
close(DATAFORM);

#----- Now build the JNOS do_beacon script using dataform as the input
system("/jnos/scripts/build_beacon hf dataform");

#----- End of dataform.plx

This very simple snippet of Perl code builds a form dynamically and then writes it to the beacon text area (config table) via build_beacon and eventually do_beacon. Therefore this script needs to be called within the framework of the beacon synchronizers that were decribed above, that is, JNOS AT and Linux cron facilities. Here is the cron line that will call this script and keep the data flows in synchrony:

  • 10,30,50 */1 * * * /bin/bash /jnos/scripts/dataform.plx 1>/dev/null 2>/dev/null

When using this cron command line, the script dataform.plx is only called at fixed, coordinated time intervals, thus keeping the timing issues under control. However, there might be other programs actually collecting "live" data. If this were the case, then dataform.plx would need to take a "snapshot" of these streams, collect and filter that data, and then present the most updated information, probably via a logfile read to Perl's format structure, generating the latest copy of the output file, dataform.

Here is what finally resides in the JNOS script do_beacon which will be sent out on the next transmission:

Dynamically Built Output Form: dataform, merged into do_beacon
# Beacon script
# 07-25-04
# KA1FSB/kbn
# --------------------------------------------------------------
# Generated on: Sat Jul 31 08:04:59 EDT 2004 by build_beacon
# Testing: A revised ID (beacon) text template
# --------------------------------------------------------------
# 
ifc hf ax25 bctext "KA1FSB-7/N (WELLS) * Network 105 * FN42jh  [Wellesley, MA]\r
   Local Time.: 08:04:58                 UTC..: 12:04:58\r
   Local WX...: Sunny w/ some clouds     Temp.: 70\r"
#
# ax25 bc hf
#
#----- End of do_beacon
Again, this is a very simple form. There could be several more updateable, dynamically refreshed, fields; latitude and longitude come to mind. (And, I have made it readable by including '\n' characters here which would normaly not be included in this file.)

The code dataform.plx has embedded the format data structure into the script itself. This should help in the understanding of how to use such a code feature. For a more versatile approach, please see the article on Setting up a Beacon Server which shows how to keep both formats and data outside the program, making a simple script into a very capable on-demand server.

EOT ...

In sum, managing your beacon events can expand way beyond the typical "signature" beacons in the world of *NOS! If used with care and judiciously, beacons can convey timely information that may prove to have great utility for the operators on the net. I encourage you to experiment with these pieces of code given here. There is still room for development and advancement in the field of Amateur Radio! We have just shifted a bit from the hardware to the software.

And, a final observation, the code presented here is really to be taken as an exemplification of a general approach to solving a few network broadcasting problems. If you like Python, Java, or C++, these concepts could certainly be re-developed within any language framework. Think about the potential "connections," many of which nearly almost already exist!


(Courtesy KBNorton Computer Services)