Most people never touch this layer, because WeeWX or CumulusMX builds the packet for you. Read it anyway if you are writing your own uploader, debugging a station that findU refuses, or trying to work out why one field is missing.
Frames and paths
APRS rides in AX.25 UI frames: unnumbered information, meaning
connectionless broadcasts with no handshake and no acknowledgement. A frame
carries a source callsign and SSID, a destination that APRS repurposes as a
software identifier (APRS generically, APDW17 for Direwolf), an optional
digipeater path, and the information field holding the actual APRS data.
The path only matters on RF. Digipeaters repeat your packet under the New-N
paradigm: WIDE1-1 is for fill-in and home digipeaters and belongs only in the
first hop position, WIDE2-1 requests one wide hop, WIDE2-2 requests two.
Longer paths are, in WA8LMF’s assessment, “almost completely useless.”
Data type identifiers
The first byte of the information field says what kind of report follows.
| Byte | Meaning |
|---|---|
! |
Position, no timestamp |
@ |
Position with timestamp, the CWOP norm |
= |
Position, no timestamp, messaging-capable |
/ |
Position with timestamp, no messaging |
_ |
Positionless weather report, discouraged |
Bob Bruninga argued strongly against the positionless form, calling it
“useless without position… an anathma for a real time system.” CWOP effectively
requires the complete position-plus-weather form, so use @.
Confusingly, _ in a positioned packet is also the weather station
symbol: symbol table / plus symbol code _ gives the blue WX icon. Same
character, two entirely unrelated jobs. This trips up almost everyone once.
The weather fields
After the position and the _ symbol, weather data is a fixed sequence of
letter-prefixed, fixed-width numeric fields.
| Field | Prefix | Width | Units | Notes |
|---|---|---|---|---|
| Wind direction | course slot | 3 | degrees true | Direction the wind is from. Required |
| Wind speed | / |
3 | mph | Sustained. Required |
| Gust | g |
3 | mph | Peak in the last 5 min. Required |
| Temperature | t |
3 | °F | Required. Negatives as t-05 |
| Rain, last hour | r |
3 | 1/100 in | Ingested by MADIS |
| Rain, last 24 h | p |
3 | 1/100 in | Ingested by MADIS |
| Rain since midnight | P |
3 | 1/100 in | Not ingested by MADIS |
| Humidity | h |
2 | % | h00 means 100% |
| Barometric pressure | b |
5 | 1/10 hPa | Mean sea level pressure, not station pressure |
| Luminosity | L / l |
3 | W/m² | L is 0–999, lowercase l adds 1000 |
| Snow | s |
3 | inches | s001 is one inch |
| Rain counter | # |
3 | counts | Raw tip counter |
Two rules bite hard in practice. The first four fields (direction, speed, gust,
temperature) are required and must appear in that order. And missing data
is written as dots, not spaces: an unknown gust is g....
The equipment suffix
This part is genuinely messy and you will see both forms in the wild.
A leading . followed by a four-character code is what WeeWX and aprx
emit: .DsVP for a Davis Vantage Pro, .Unkn when it does not know. A
leading e followed by a free-form string is the other convention; per
Philip Gladstone’s aprswxnet page, “please include the version number of your
software and the type of hardware… For example: eMyWx123DVP.” Cumulus emits
eCumulus and eCumulusFO.
Do not go looking for a tidy scheme underneath. The gladstonefamily hardware
table maps numeric codes (31 is a Davis Vantage Pro, 400 an Acu-Rite
5-in-1, 232 a WMR100) while the original DOS-era APRS documentation used a
letter-led scheme (d for DOS, U2k for an Ultimeter 2000, Dvs for Davis)
that is now essentially historical.
Worked examples
The canonical CWOP example, from wxqa:
EW9876>APRS,TCPIP*:@060151z3316.04N/09631.96W_120/005g010t021r000p000P000h75b10322
Reading it left to right:
| Piece | Meaning |
|---|---|
EW9876>APRS,TCPIP*: |
Source EW9876, tocall APRS, injected over the internet |
@ |
Position with timestamp |
060151z |
Day 06, 01:51 UTC |
3316.04N/09631.96W |
33°16.04′N, 096°31.96′W, with leading zeros required and exactly two decimals of minutes |
_ |
Weather station symbol; wind follows |
120/005 |
Wind from 120°, 5 mph sustained |
g010 |
Gust 10 mph |
t021 |
21 °F |
r000 p000 P000 |
No rain in the last hour, 24 hours, or since midnight |
h75 |
75% relative humidity |
b10322 |
1032.2 hPa MSLP |
And one generated by Direwolf, using ! with no timestamp:
HAM1>APDW17:!1220.40N/05646.80E_220/004g005t077r000p000P000h50b09900
Wind from 220° at 4 mph, gusting 5, 77 °F, 50% humidity, 990.0 hPa.
Timestamps
Three formats exist. You want the first.
DHM is day, hour, minute plus a zone character, as in 060151z, where z means
UTC. This is what CWOP uses. HMS is hour, minute, second followed by
h, intended for high-rate or moving stations. MDHM is month, day, hour,
minute as eight digits, always UTC, used mostly in object reports.
Use DHM with z, and send UTC. One caveat from wxqa: findU timestamps packets
on arrival, because station clocks drift, so the time in your packet is
informational rather than authoritative.
The APRS-IS handshake
Connect over TCP to port 14580. The server sends a banner, which you ignore. Send exactly one login line, CR/LF terminated:
user EW9876 pass -1 vers WxAlertsUploader 1.0
user is your CWOP ID or callsign, pass is -1 for CWOP or your computed
passcode as a ham, and vers is your software name, with no spaces, plus a
version. The server acknowledges; ignore that too. Then send your weather
packet, with all header letters uppercase. There is no application-level
acknowledgement, since TCP already handles delivery. Disconnect.
Servers:
cwop.aprs.net:14580 (also :23) |
The four CWOP servers behind one name |
rotate.aprs2.net:14580 |
The Tier 2 rotating pool |
noam.aprs2.net:14580 |
Regional rotate, for lower latency |
Always defer to the current “APRS Servers to Use” list on wxqa.com. Several widely-circulated CWOP setup PDFs predate the present recommendations.
The filter syntax on port 14580 (r/lat/lon/dist, p/prefix, t/wx) only
matters if you are also consuming the stream. A pure uploader ignores it.
Report every five minutes
wxqa is explicit: no faster than one packet every five minutes. This is not arbitrary politeness. Five minutes is MADIS’s own processing cadence, so reporting faster gains nothing at the destination, wastes shared bandwidth, and trips duplicate suppression that can get your station flagged.
The specifications
- APRS101.PDF: the APRS 1.0 protocol reference, chapter 12 is weather. Dates to 2000 and is stable but old.
- aprs.org/aprs11/: the 1.1 addenda, including
spec-wx.txtandSSIDs.txt. - aprs.org/aprs12/weather-new.txt: 1.2 proposals, with extended fields for flood, radiation and battery.
- PROTOCOL.TXT: Bruninga’s original on-air formats.
Bruninga (WB4APR), who created APRS, died in 2022. The APRS Foundation now stewards the standard.
Where to go next
- From a station you already own: including a dependency-free Python uploader that implements this page.
- On the air: putting the same packet out over RF.
- Install and commissioning: decoding your own packets locally before you trust them.
