README
¶
stationmaster
Multifunction software for running a ham radio station. The user interface for the application is a browser pointed to localhost:4000.
Functions:
- Morse code practice oscillator
- Morse code keyer for radios that don't have one
- Station contact logger - log editor
- Analysis functions to review contact progress
- Building ADI files for upload to the LOTW and updating logs from downloads
- Contest mode to minimize keystrokes during contests
- Building Cabrillo files for submitting contest logs
- Interface to DX Spiders and display of active users on the VFO page
- Interface to the Ten Tec (or any other radio) band switch to automatically know the band
- Interface to a DDS frequency synthesizer to control the radio frequency
- Interface to the WSJT-X application for logging FT8/FT4 contacts
- Interface to QRZ.com for pulling in contact information
- Contest page
Additional software and hardware
In addition to this software, you will also of need:
- MySQL database (required)
- A Morse code subsystem (optional)
- A VFO subsystem (optional)
- An amature radio license and call sign to access DX Siders (optional)
- Local installation of WSJT-X softare (optional)
- QRZ.com account (required)
Contesting subsystem
With the recent updating of the contesting part of the program, I have added a new "contests" table to the database. More on that in the database section below.
Contesting is configured using the defaults page. Here are the required steps:
- Set the operating mode (CW, USB, LSB etc.)
- Set the band (10m, 15m...)
- Set the contest mode to yes
- Enter the contest name (make it unique since it is used to generate Cabrillo files)
- Enter the contest start date
- Enter the contest start time (band, mode, and start date and time are used to check for dupes)
- Select the number of fields required for the contest (application permits a range of 2 to 5)
- Enter the names of the fields seperated by commas, followed by "enter"
- The selected number of fields and the number of fields entered must match
- The named fields appear
- Enter what you will be sending (the automated sequence generation not built yet)
- Click submit
- Click on the contest button on the top navigation band
- You should see the fields that you are required to enter layed out on the page
- If one of the fields starts with letters RS, it is automatically filled with 599 as you tab over to it
- Hitting enter or CR will log the contact.
- All displayed fields are required
Morse code subsystem
The Morse Code oscillator subsystem interfaces to the stationmaster software through a USB inteface. I am currently using an Arduino and a USB to serial converter to connect. The code for the Arduino is in my GitHub page and it is called newCW. In additoin to the Arduino and the USB to serial convertor, the subsystem also contains a class D audio amp that drives an 8 ohm speaker and a software programmabe attenuator for volume control and a reed relay to drive the radio. The practice oscillator tone is generated by the Arduino. The USB to serial convertor, the amplifier and the attenuator are all modules sold by Adafruit. The relay and the speaker are available from Amazon.
VFO subsystem
The VFO sybystem interface is also a USB interface and uses a USB to serial convertor to connect. Arduino drives a NuElec DDS module. This module incorporates an Analog Devices DDS chip and additional necessary components. The output of the DDS directly drives the radio VFO input. The NuElec DDS module is available from Amazon.
The VFO module also reads the radio band switch. Even though given the pin count of the Arduino Uno R4 Minima a diode encoder is not necessary, since I am using part of a printed circuit board I made for another project I do encode the 8 switch settings into a 3 bit code that is read by the local Arduino. If you plan to skip the diode ecoder (you should), you need to change the Aruino code which is also available on my GitHub page and it is called newVFO.
These two subsystems are connected to the Raspberry Pi (shortly replaced with a Mac Mini) with USB cables through a USB expander. This approach allows for the addition of future peripherals such as an antenna tuner.
If your radio is modern and has a keyer and oractuce oscillator built in and has a CAT interface, you can skip much of this and add HamLib to the package (there is a Go binding to it) and be done. I might replace my Ten Tec Omni D with a modern radio one of these days and do the same.
Database
The database in MySQL is called stationmaster. It has four tables. They are stationlogs, qrztable, defaults, and stashtable. The scripts for building these tables are in the dbscripts directory.
The details of the table structures and how to build them is at the end of this note.
A few notes on the logger (and other screens):
- The callsign search window let's you search for the call sign prior to a QSO, get info about a contact, and find out if you have worked them before?
- The add button (next to the logger button) on the top ribbon is how you add a QSO. You only see the add button if you have clicked the logger button.
- If you have set the defaults (using the default button on the top ribbon), the band and mode show up on the add window. If you are using the VFO subsystem (or equivalent), there is no need to set the defaults. The software reads and infers them from the band and frequency information.
- After you move the curser out of the call sign window, the system looks up the call sign from the local database or from QRZ.com and update the add window, then you only need to add the RST sent and received and any comments.
- If you need to edit the entry, click on the ID link.
- If you need to see more detail on the contact, click on the call sign.
- When the application makes an API call to QRZ, it stores all of the information obtained from QRZ in the database. It only displays some of that information. Some of it is used later in features like county summary. The rest is just stored for future analysis.
- In the default page, in addition to the band and mode, you can set the contest mode, the contest name, and the contest exchanges. When you are in contest mode, it will add them to the add page so you don't have to type them in.
- When in the contest mode, non contest logs are hidden.
The analysis tab is all self explanatory. I will be adding additional analytics as the needs arise.
The ADIF button brings up the page for generating or updating LOTW status.
- On the ADIF page, only logbook entries with blank LOTW Sent field are displayed. Once LOTW file is generated, this field is set to YES.
- For uploading the ARRL ADIF file, put the filename window and push the update QSL button.
The generated and uploaded ADIF files are in the the ADIF directory in the configuration file. The configuration chain works as follows:
- The program depends on the directory structure as it is laid out.
- The top of the configuration chain is the environment variable STATIONMASTER
- STATIONMASTER points to the file config.yaml.
- The QSL log is referenced to the $HOME environment variable.
The Cabrillo button brings up the Cabrillo file generation page. All the fields on this page are required. All dates and times are in UTC. The file is stored in the contest directory as specified in the config.yaml file.
The contest page depends on the entries in the defaults page for band, mode, RS(T) and exchange sent. Today, I do not have direct integraton into the radio for sending code and in the case of anything other than my interfaces into the Ten Tec, for reading band and frequency. That will come later.
A final note:
- I am building this as a single user local application
- It was originally intended to run on a Raspberry Pi as the station controller, though I originally developed the application on a Mac. I am moving it to a Mac Mini.
- It also depends on specific hardware as I have described above.
I have taken some liberties with how I have used the Go web libraries. If this was a multi-user application meant to be accessible on the Internet, you would not do some of these and add other functionality that I have not included.
Database installation
I have tested this on a MAC and on a Raspberry Pi running Linux.
This is my way. You may have better ways in which case you can use them.
- Make sure you have homebrew installed
- Run "brew install mysql" (it installs mysql without password which fine)
- To restart mysql at each login run "brew services start mysql"
- If you want to secure the installaton run "mysql_secure_installation" (I have not)
- Run "mysql -u root" now you are at the mysql prompt (note that root user has access)
- You can run "SHOW DATABASES;" and see that there are only native system databases there.
- Create the "stationmaster" database by running:
CREATE DATABASE stationmaster CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- And run "SHOW DATABASES" again and you should see stationmaster in the list.
- Run "USE stationmaster;" and you will switch to the stationmaster database
- Run "SHOW TABLES;" and you should see an empty set
- Now you are ready to build the four tables: defaults, qrztable, stashtable, and stationlog
- See the table schemas below to see how these tables are structured.
- Run "source makelogtable.txt;" to build the stationlogs table
- Run "source makeqrztable.txt;" to build the qrztable
- Run "source makestashtable.txt;" to build stashtable
- Run "source makedefaulttable.txt;" to build defaults table
- Create user by running "CREATE USER 'web'@'localhost';"
- Give user permiissions by running:
"GRANT SELECT, INSERT, UPDATE, DELETE ON stationmaster.* TO 'web'@'localhost';"
- Set password for the user (use a password of your choosing instead of "password"
ALTER USER 'web'@'localhost' IDENTIFIED BY 'password';
- Init the stash table by running "source initstash.txt;"
- Quit mysql
- Init defaults table by running (at the os prompt) "mysql -u root stationmaster < initdefaults.sql"
- Set the environment variable STATIONMASTER to the root directory of the project.
- For example in ~/.zshrc
STATIONMASTER=$HOME/Documents/gocode/src/stationmaster export STATIONMASTER
Now you can run the program.
STATIONMASTER TABLE STRUCTURE
This is the schema for the stationlogs table. The file makelogstable.txt in the dbscripts folder generates this table when run in batch mode. This table has been updated to reflect the additional contesting functionality.
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int | NO | PRI | NULL | auto_increment |
| time | datetime | NO | MUL | NULL | |
| callsign | varchar(20) | NO | MUL | NULL | |
| mode | varchar(20) | NO | NULL | ||
| sent | varchar(10) | NO | NULL | ||
| rcvd | varchar(10) | NO | NULL | ||
| band | varchar(10) | NO | NULL | ||
| name | varchar(100) | NO | NULL | ||
| country | varchar(100) | NO | NULL | ||
| comment | varchar(100) | NO | NULL | ||
| lotwsent | varchar(20) | NO | NULL | ||
| lotwrcvd | varchar(20) | NO | NULL | ||
| lotwqsodate | datetime | NO | 1970-01-02 00:00:00 | ||
| lotwqsldate | datetime | NO | 1970-01-02 00:00:00 | ||
| contest | varchar(5) | NO | No | ||
| exchsent | varchar(10) | NO | |||
| exchrcvd | varchar(10) | NO | |||
| contestname | varchar(50) | NO | |||
| field1Sent | varchar(10) | NO | NULL | ||
| field2Sent | varchar(10) | NO | NULL | ||
| field3Sent | varchar(10) | NO | NULL | ||
| field4Sent | varchar(10) | NO | NULL | ||
| field5Sent | varchar(10) | NO | NULL | ||
| field1Rcvd | varchar(10) | NO | NULL | ||
| field2Rcvd | varchar(10) | NO | NULL | ||
| field3Rcvd | varchar(10) | NO | NULL | ||
| field4Rcvd | varchar(10) | NO | NULL | ||
| field5Rcvd | varchar(10) | NO | NULL |
If you note, I store very little user information in the stationlogs table (I should store nothing but the call sign). The detail information is stored in the qrztable and here is the schema (note tht qso_count is not QRZ.com data, it is simply the count of how many QSOs I have had with this contact.
Note in the script for building this table for MariaDB, there is no foreign key since MariaDB did not support it when I first built the tables (and it may still not support it). But the software does not depend on it.
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int(11) | NO | PRI | NULL | auto_increment |
| time | datetime | NO | NULL | ||
| callsign | varchar(20) | NO | UNI | NULL | |
| aliases | varchar(50) | NO | NULL | ||
| dxcc | varchar(5) | NO | NULL | ||
| first_name | varchar(100) | NO | NULL | ||
| last_name | varchar(100) | NO | NULL | ||
| nickname | varchar(50) | NO | NULL | ||
| born | varchar(5) | NO | NULL | ||
| addr1 | varchar(50) | NO | NULL | ||
| addr2 | varchar(50) | NO | NULL | ||
| state | varchar(20) | NO | NULL | ||
| zip | varchar(10) | NO | NULL | ||
| country | varchar(50) | NO | NULL | ||
| country_code | varchar(5) | NO | NULL | ||
| lat | varchar(15) | NO | NULL | ||
| lon | varchar(15) | NO | NULL | ||
| grid | varchar(10) | NO | NULL | ||
| county | varchar(50) | NO | NULL | ||
| fips | varchar(10) | NO | NULL | ||
| land | varchar(50) | NO | NULL | ||
| cqzone | varchar(5) | NO | NULL | ||
| ituzone | varchar(5) | NO | NULL | ||
| geolocation | varchar(10) | NO | NULL | ||
| effdate | varchar(10) | NO | NULL | ||
| expdate | varchar(10) | NO | NULL | ||
| prevcall | varchar(10) | NO | NULL | ||
| class | varchar(5) | NO | NULL | ||
| codes | varchar(5) | NO | NULL | ||
| qslmgr | varchar(100) | NO | NULL | ||
| varchar(50) | NO | NULL | |||
| url | varchar(50) | NO | NULL | ||
| views | varchar(20) | NO | NULL | ||
| bio | varchar(50) | NO | NULL | ||
| image | varchar(150) | NO | NULL | ||
| moddate | varchar(30) | NO | NULL | ||
| msa | varchar(5) | NO | NULL | ||
| areacode | varchar(5) | NO | NULL | ||
| timezone | varchar(20) | NO | NULL | ||
| gmtoffset | varchar(5) | NO | NULL | ||
| dst | varchar(3) | NO | NULL | ||
| eqsl | varchar(3) | NO | NULL | ||
| mqsl | varchar(3) | NO | NULL | ||
| attn | varchar(100) | NO | NULL | ||
| qso_count | int(11) | NO | NULL |
The stashtable is identical to the qrztable and it is used to stash data on a temporary basis to avoid multiple calls to qrz.com during one transaction.
The defaults table stores system data such as frequency by band, mode, fixed
constest exchanges, and the like to make the user intrface a little nicer.
It is a simple key value pair and the software uses it as needed by specifying
a key and associating a value with it.
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int(11) | NO | PRI | NULL | auto_increment |
| kee | varchar(20) | NO | MUL | NULL | |
| val | varchar(100) | NO | NULL |
A new table was added to store contest names, the start time, the number of fields and names of the required fields. This is to help generate Cabrillo file (and other reports) as required in the future even if the logger is not in the contest mode or other contests have come and gone and the data in the defaults table is overridden.
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int | NO | PRI | NULL | auto_increment |
| time | datetime | NO | NULL | ||
| contestname | varchar(50) | NO | MUL | NULL | |
| fieldCount | tinyint(1) | NO | NULL | ||
| field1Name | varchar(10) | NO | NULL | ||
| field2Name | varchar(10) | NO | NULL | ||
| field3Name | varchar(10) | NO | NULL | ||
| field4Name | varchar(10) | NO | NULL | ||
| field5Name | varchar(10) | NO | NULL |