The API over RF
You can build a simple API client with a radio and no internet connectivity.
Four bot commands have a machine form: CQ,
INFO, TIME and CHASERS.
Each is the ordinary command with
! immediately following the keyword. The machine forms take the same arguments
as their human-friendly counterparts. The replies to the machine forms are made
of fields in a well-defined order instead of a human-readable sentence. Each
command’s page documents its exact reply under “Machine form”. This page
explains the common grammar.
Not all bot commands have a machine form. The commands that change something, a
HOST, a CHASE, a QSL, answer with confirmations and hints, not data, so they
have no machine form.
The bang
The machine form is a bot command with ! (sometimes called a bang) appended,
i.e. CQ!, INFO!, INFO! K7ABC, TIME!, CHASERS!. As with every command, case does
not matter. The bang doesn’t work on q-code synonyms, so QRT?! is not
recognized. CQ ! (with a space before the bang) is an ordinary CQ command
with trailing text, which the CQ command ignores.
I chose ! because APRS forbids | and ~ in message text, ? opens a directed
query and is part of QRT?, - joins a callsign to its SSID so CQ-6 reads as
a station, and / is a path and grid character. ! is visually distinctive and
carries the “do it now” meaning for most programmers.
The reply grammar
- The reply begins with the command that initiated it. APRS gives you no
correlation between your query and OTA’s reply. Messages may arrive out of
order. The APRS ack only confirms receipt of your message, and its response
arrives later as an unrelated message. Send
CQ!and it answersCQ! ..., so your parser can dispatch on the first token and doesn’t have to try and figure out which command initiated this response. - Fields are positional, separated by a single space, with no free text
inside a record. The sixty-seven character limit of an APRS message does
not make key=value pairs practical. Fields are not quoted and can’t contain
spaces. The one exception is the description message: when the host
described their op,
INFO!sends a separate message of the command, the station, the literalDESC, and then the host’s text to the end of the message.DESCsits where a record has a grid or_and a miss hasNIL, so switch on the third token. Free text never appears inside a record. _in a field is null. In json this would show up asnull. Not every field can contain this value, but you should check for it before coercing a field value to a number.NILmeans the record was not found: If you use theINFO!command to ask about a callsign that doesn’t have an op on the air, you’ll getNILback.- Number formats. Most numbers are bare integers. A time is whole minutes
from now. A position is latitude then longitude in signed decimal degrees
with four digits after the decimal point. A missing or unknown position
is
_ _, so the fields after it keep their positional places. - New fields append, never insert, and your parser must ignore fields past the ones it knows. This is the RF adaptation of the HTTP API’s additive rule. We will only ever add to the end of a response. You should tolerate and accept responses with more fields than you expect.
The op record
CQ! and INFO! both transmit information about ops, and they share some fields.
CQ! sends the first three fields for each op. INFO! sends all of them.
A CQ! response may have multiple records, each of which is a prefix of an
INFO! record. There is no record delimiter. Your parser consumes three fields
per op. The order of the fields is the op object’s wire
order and it is shown on each command’s page.
Paging
CQ! and CHASERS! can return a response that is more than one APRS message.
Here’s how it works, with CQ! as the example:
- The bot will send no more than three messages as its response.
- Each message starts with
CQ!, this message’s number and the total number of messages that comprise the response, and the total number of ops on the air. Everything after is the data about ops. - The fields for a single op will never be spread across multiple messages.
- The ops are in order, with those going off the air first at the beginning of the sequence.
- You can check the total number of ops field to know whether some ops had to be omitted from the response.
- The
n/Non every message lets you notice a page that never arrived or arrived out of sequence. - When no ops are on the air you will receive
CQ! 1/1 0.
CHASERS! pages the same way. CHASERS!, then n/N, then the total number of
chasers waiting, then one station call per chaser, longest waiting first. Nobody
waiting is CHASERS! 1/1 0.
No matter how many pages (aka messages) come back to you, it counts as one query
against the command’s rate limit. The machine forms share the human forms’
limits and budgets throughout. A client cannot double its budget by alternating
forms, and a client that trips an error condition, TIME! from the wrong
station or a bare INFO! with no op, gets the same hint a human would.
Examples
A CQ! with five ops on the air, answered in two messages. The op with the
least time left comes first, and WB4BOR-5 has no grid:
INFO! about a station that is hosting, answered with the whole op record.
The host described this op, so the description message comes first:
An op with no description gets only the record. The description is cut to fit one message, and the two messages may arrive in either order.
INFO! about a station that is not hosting:
TIME! from the station running the op. The reply is the minutes left, then
the minutes to the two-hour cap:
CHASERS! from the station running the op, with three chasers waiting on a
QSL, the one who has waited longest first: