Repository navigation
Releases: smashingwaffle/pytnc-pro
Release list
PyTNC Pro v0.1.8-beta
PyTNC Pro v0.1.8-beta — Release Notes
Big feature release. APRS messaging comes out of scaffolding, VARA FM gets a real chat feature, audio device handling is overhauled, and the first working environmental monitor (AQI) lands against the new AirNow API.
💬 APRS Messaging (new)
APRS messaging is now embedded directly in the APRS tab (right side, below the symbol picker) — no separate tab needed.
- To / From callsigns with auto-uppercase
- Live 67-character counter (amber at 60, red at 67)
- Explicit "IS" and "RF" send buttons — you choose the transport per message
- ACK tracking — outgoing messages show ⏳ pending, ✓ acked, ✗ no-ack
- Terminal-style message log with color-coded callsigns and status markers
- Recent dropdown — one-click fill of the last 10 callsigns you've messaged
- Right-click any log line → Reply / Copy text / Resend / Clear view
- Persistence — conversations saved to
pytnc_conversations.json, restored on next launch - Tab-title flash — APRS tab shows
📻 APRS 💬*on incoming message, clears when you switch to it - Auto-ACK reply — when someone messages you and requests an ACK, PyTNC sends it back
- Bulletin filtering —
BLN*/NWS*addressees stay out of the conversation log
📡 VARA FM Chat (new)
Full peer-to-peer chat over VARA FM connected sessions. Lives in the VARA FM tab (right side, below the symbol picker).
- Target callsign field with Recent dropdown of previously-linked stations
- 🔗 Link / ✂ Unlink buttons with live status (
○ idle/◐ linking…/● linked to X/◐ disconnecting…) - Color-coded chat history — outgoing in cool blue with
→, incoming in warm amber with←, system events in italic teal - Auto-accept incoming calls via VARA's
LISTEN ON(no manual accept needed) - Persistence — chat history saved per remote callsign to
pytnc_vara_chat.json - VARA tab flashes
📡 VARA FM 💬*on incoming chat - Right-click chat log → Copy line / Clear view
- 🐛 Debug toggle — surfaces VARA daemon internals: IAMALIVE/BUSY events, per-cycle PTT counts, raw data-socket hex bytes, periodic link-state summaries
🔊 Audio System Overhaul
- Audio API filter (defaults to MME, matches VARA FM) — device pickers now show one row per physical device instead of 3-4 duplicates across Windows audio APIs
- "Show all" toggle for advanced users who want the full list
- Always-on RX level meter on the Settings tab — see audio levels live without starting receive
- TX audio TX levels honored correctly — matches Send Beacon's proven pattern for messages sent via RF
⭐ Device Aliases (new)
Right-click any RX / TX / PTT / GPS device combo → give it a friendly name.
- Right-click → Rename / Clear alias / Copy device name
- Display format:
⭐ DigiRig RX · 1: USB Audio CODEC [MME] 44100Hz 2ch - Aliases persist across restarts in
pytnc_settings.json - Audio device selections now saved by name+API — surviving Windows device renumbering when USB ports change
💨 Air Quality Index (AQI) — new API
First working environmental monitor. Built against the June 2026 AirNow API (/aq/forecast/current/), so it won't break when AirNow retires the legacy endpoints on September 30, 2026.
- Fetches current AQI forecast for your beacon location
- Colored EPA badge on the map at your position (Good / Moderate / USG / Unhealthy / Very Unhealthy / Hazardous)
- Status label shows
AQI 56 · Moderate · PM2.5 · ⚠️ Action Day - Hourly auto-refresh with manual 🔄 refresh button
- Full popup with pollutant, reporting area, forecast agency, and discussion narrative
- Rate-limit safe (24 requests/day per user vs AirNow's 500/hour cap)
🏗 Layout Changes
- APRS tab: TX Log moved to bottom of left panel (fills remaining vertical space); right panel is now Symbol Picker (½) + APRS Messaging (½)
- VARA FM tab: mirrors the same layout — VARA log at bottom-left, chat on right
- VARA tab log: small 🗑️ Clear button now sits top-right of the log (was a wide button below)
🐛 Bug Fixes
- VARA
REGISTEREDno longer flips link state to True — was causing false "already linked" errors after daemon connect. OnlyCONNECTED <src> <dst>marks a real P2P link now. - Removed erroneous auto-CONNECT on incoming RING — was colliding with VARA's LISTEN-ON acceptance and breaking handshakes. VARA handles acceptance internally.
- MYCALL / CONNECT source mismatch fixed —
_vara_chat_linknow uses the exact MYCALL string that was registered with VARA, preventing endless-retransmit loops when SSID differs between UI callsign field and registered MYCALL. - VARA TX-indicator error no longer aborts sends — cosmetic indicator wrapped in try/except so chat send always completes.
- Old obsolete
setTabText(2, ...)writes removed — was writing "💬 Messages" over the Info tab (leftover from a previous refactor). - Placeholder methods replaced with working implementations —
_vara_send_chat,_toggle_aqi_monitor,_rx_toggle_aqi,_fetch_aqi_datawere all referenced-but-undefined; would have crashed on click. _load_conversations()added — previously missing, so restored APRS messages weren't loading from disk.
⚙️ Technical
- New JSON files:
pytnc_conversations.json(APRS messaging),pytnc_vara_chat.json(VARA chat per-remote) - New settings keys:
device_aliases,audio_preferred_api,audio_show_all_apis,settings_rx_audio_key,settings_tx_audio_key,audio_device_key,tx_device_key - New dependencies: none — all built on existing
sounddevice,PyQt6,requests,scipy - Backward-compatible with v0.1.7-beta settings files (new keys default sensibly if absent)
- Version:
main.pyandpytnc_config.pyboth bumped to0.1.8-beta
📻 Verified Working (Test Setup)
FT-991A + DigiRig on rear DATA port (Pin 5), 1200-baud APRS RF TX/RX working end-to-end with:
- TX Level 8%, RX Gain 0.1x (typical for narrowband packet through DigiRig)
- Menu 070 = REAR, 071 = DAKY, 079 = 1200
VARA chat verified working via FT5 ↔ FT-991A in wide/9600 mode with Pin 5 wiring.
🙏 Acknowledgments
Big session, big release. Sorry for the delay, was working all summer...
I will start a user account in the next version so I can keep track of the amount of actual users.
prbably start another tab for Mail in varafm , a winlink kind of version...
more to come
73 de KO6IKR, Belgium, Los Angeles
PyTNC Pro v0.1.7-beta
PyTNC Pro v0.1.7-beta Release Notes
Released: April 2026
Callsign: KO6IKR
GitHub: https://github.com/smashingwaffle/pytnc-pro
*Hi everyone, just spend a week in Hawaii chasing underwater life, mostly under the hood improvements this time. RF decode rates should be noticeably better. Also added APRS Objects which is something most desktop APRS programs don't do well. I also took out regional stuff to LA... Would love to get more feedback on this app, as I am not sure who is using this. Just email me and I'll be happy to do a mailing list. KO6IKR@gmail.com, 73de KO6IKR, Stefaan *
📻 RF Improvements (Big One)
- AFSK Pre-emphasis added — the 2200Hz space tone is now boosted before transmission to compensate for de-emphasis built into VHF FM receivers. This is standard Bell 202 practice and dramatically improves decode rates at remote stations. If you were struggling to get through on RF, this should fix it.
- Preamble increased from 60 to 80 flags (~530ms) — gives decoders more time to lock on before the packet starts
📌 APRS Objects (New Feature)
- New 📌 APRS Objects button in the APRS tab opens a dedicated floating window
- Create named objects (up to 9 chars) with custom position, symbol and comment
- Beacon via APRS-IS or Beacon via RF — uses full TX pipeline with PTT
- Objects saved to
pytnc_settings.jsonand reload on startup - Standard APRS object packet format per spec
- Use cases: EmComm command posts, nets, events, hazards
🗺️ Map Fixes
- Map jumping fixed —
setViewguard blocks Leaflet internal pans; only explicitpanToStationcan move the map - Popup positioning fixed — 200ms delay after
setViewensures popup renders at correct position in QWebEngineView - Icon flicker fixed —
setIcononly called when icon actually changes, preventing marker flash on packet update - Station age fading — fresh stations full opacity, aging stations fade, old stations dim
🔧 General Fixes & Improvements
- 30-second duplicate suppression — RF and APRS-IS share the same dedup dict; same packet arriving via multiple paths only logged once (matches aprsc/Dire Wolf standard)
- Auto-save removed from beacon —
send_beaconno longer callssave_settings()on every transmission - APRS TX log timestamps —
[HH:MM:SS]on all TX log entries - IGate beacon — new Frequency, Mode (Rx/RxTx) and Location fields
- IGate lon bug fixed —
cannot access local variable 'lon'on RX IGate start - PTT serial crash fixed — clean error dialog instead of crash when radio disconnected
- Deprecated
utcnow()replaced withdatetime.now(timezone.utc) - Send buttons — APRS-IS and RF buttons now side by side
- Interval + Mode on same row in Auto-Beacon section
- DARN layer removed — was LA/SoCal specific,
- Info tab — removed regional links, added PyTNC Pro Wiki
📦 Installation
Download the latest release from the Releases page.
Extract and run PyTNC_Pro_v0.1.7-beta.exe no installation required.
See the Wiki for setup and supported hardware.
New dependency: scipy is now required for the pre-emphasis filter.
If running from source: pip install scipy
73 de KO6IKR 📻
PyTNC Pro v0.1.6-beta
PyTNC Pro v0.1.6-beta Release Notes
Released: April 2026
Callsign: KO6IKR
GitHub: https://github.com/smashingwaffle/pytnc-pro
Yes it is going fast, but that is what happens with Beta releases. Found a few bugs and bug-ettes... Email me for feature requests... Hoping to get a RepeaterBook API so I can implement repeaters in. I also took some of my local stuff out, like DARN and LA based links from the info tab.
🗺️ Map Improvements
- Popup positioning fixed — popups now open correctly centered above the station icon when clicking from the live feed (QWebEngineView rendering delay resolved)
- Map jump bug fixed — intercepted rogue Leaflet
setViewcalls that were causing the map to jump to random stations when new packets arrived - Click behavior — click any station icon to open popup, click again to close, click empty map area to dismiss
- Show Last dropdown — filter map stations by age: 15 min, 30 min, 1 hr, 3 hr, 6 hr, 12 hr, 24 hr
- Station age fading — stations fade as they age: fresh (<30min) = full opacity, aging (30min–2hr) = 40%, old (>2hr) = 25%
- DARN layer removed — was LA/SoCal specific; universal repeater layer coming in a future release via RepeaterBook API
⛰️ Elevation (Topo)
- Automatically fetches elevation from Open-Meteo when GPS fix is acquired
- Elevation shown in APRS tab and VARA FM tab below GPS coordinates
- Elevation appended to all beacons as
/A=000519(standard APRS altitude extension) - Elevation shown in your station popup on the map
- Only re-fetches if you move more than 100m
📡 Beacon Improvements
- Station popup now shows:
PyTNC Pro v0.1.6-beta+ radio model + elevation + timestamp - IGate beacon enhanced with dedicated config fields: frequency monitored, RX/TX mode, location description
- IGate beacon now plots your station on the local map with
I&symbol - IGate lon bug fixed — was causing
cannot access local variable 'lon'error on startup - PTT serial crash fixed — no more crash when radio/interface is disconnected while app is running
🔧 Code & Architecture
monitors.pymixin split — moved all overlay monitors (earthquakes, AQI, fires, hospitals, weather, locations, tile cache) out ofmain.pyintotnc/monitors.py— removed ~1,953 lines frommain.py- Log autoscroll pause — scrolling up in the live feed pauses autoscroll; returns to bottom resumes it
📋 Info Tab
- Removed regional links (LAXNORTHEAST, LA County EMS)
- Removed Software & Tools section
- Added RepeaterBook to Repeaters & Frequencies
- Added PyTNC Pro Wiki section linking to GitHub wiki
🐛 Bug Fixes
- IGate beacon
lonvariable not set when GPS fix active - PTT serial
SerialExceptioncrash when radio disconnected - APRS-IS not connected error now also shown in APRS TX log
pytnc_config.pyversion string updated tov0.1.6-beta
📦 Installation
Download the latest release from the Releases page.
Extract and run PyTNC_Pro_v0.1.6-beta.exe — no installation required.
See the Wiki for setup and supported hardware.
73 de KO6IKR 📻
PyTNC Pro v0.1.5-beta
PyTNC Pro v0.1.5-beta — Release Notes
Released: April 2026
TOCALL: APPR01
Python: 3.10–3.12 (3.12 recommended)
GitHub: https://github.com/smashingwaffle/pytnc-pro
Highlights
v0.1.5 is a deep protocol compliance release. Every area of the IGate implementation was audited against the authoritative APRS-IS specification and WB2OSZ's Understanding APRS Packets (February 2026 edition). The result is a substantially more correct IGate, a fixed third-party packet pipeline, and a cleaner live feed.
🌐 IGate — Full Protocol Compliance Audit
The IGate was audited line-by-line against:
- http://www.aprs-is.net/igating.aspx (APRS-IS IGate Design)
- http://www.aprs-is.net/IGateDetails.aspx (IGate Gating Criteria)
- WB2OSZ Understanding APRS Packets §2.6 Third Party header
Critical Fix — Third-Party Packet Unwrapping
This was a silent messaging bug. } (third-party) packets arriving on RF were classified as Other and discarded. This meant:
- Messages relayed from APRS-IS → TX IGate → RF were never processed
- No ACK was sent back to the sender
- The message never appeared in the message inbox
Third-party packets are now properly unwrapped: the } wrapper is stripped, the inner packet is re-parsed, and messages are delivered normally.
TX IGate Third-Party Format Fixed
The mandatory RF format is now spec-compliant:
IGATECALL>APRS,GATEPATH:}FROMCALL>TOCALL,TCPIP,IGATECALL*:data
Previously, APRS-IS path elements (qAR, qAC etc.) were leaking into the RF packet. The spec is explicit: q constructs must never appear on RF.
New TX IGate Gating Criteria
Two missing criteria from the spec were added:
- Criteria 2: Don't gate a message to RF if the sending station was recently heard on RF (they don't need internet delivery)
- Criteria 4: Don't gate a message to RF if the receiving station is internet-connected (
TCPIP*in path)
Other IGate Fixes
| Fix | Detail |
|---|---|
TCPXX added to all path checks |
Was only checking TCPIP |
Generic query ? packets blocked |
Per spec: must not gate to APRS-IS |
?IGATE? query now responded |
Replies with <IGATE,MSG_CNT=n,LOC_CNT=n capabilities |
| TX heard window default 30→60 min | Spec says 1 hour |
| TX IGate RF dedup | Same packet won't re-transmit to RF within 60s |
| APRS-IS login version string updated | Now sends PyTNC-Pro 0.1.5-beta |
📦 Packet Parser Improvements
New Packet Types
| Type | DTI | What changed |
|---|---|---|
| Killed object | ;NAME_ |
Now removes station from map via removeStation() |
| Item report | ) |
Now parsed — live ! and killed _ both handled |
Objects and items now try compressed position format first, with uncompressed as fallback.
Comment Cleaning
| Problem | Fix |
|---|---|
DAO !wpg! !wYa! showing in comments |
Was case-sensitive !W..!, now catches ![Ww].{2}! |
!x! matched any char |
Spec says literal lowercase x — fixed to .replace('!x!', '') |
RNG0001 70cm Voice D-Star... showing RNG prefix |
Strip RNG#### prefix used by D-Star/DMR/C4FM gateways |
Base91 |..| telemetry showing as garbage |
Strip pipe-delimited base91 blocks |
| Kenwood TM-D710 0xFF/0x00 bytes | Strip on decode before any parsing |
| Trailing CR/LF in RF packets | Strip before processing (IGate spec requirement) |
🗺️ Map & Display
Voice Frequency Tooltips
Station popups now display voice frequency, tone, and offset when present in the comment:
📻 145.450 MHz PL100 -600kHz
Parser now handles real-world variations:
145.450MHz(3 decimals, spec format)445.02500MHz +0.0000MHz(5 decimals, DMR gateway format)1288.450 -12MHz(no MHz suffix on offset)
Killed Objects/Items Removed from Map
When a killed object (_) or item (_) packet is received, the station marker, label, and trail are immediately removed from the map.
window.removeStation() Added
New JavaScript function in the map for programmatic station removal.
🐛 Bug Fixes
| Bug | Fix |
|---|---|
| Auto-beacon runaway — fired every second | Minimum 1-minute interval enforced |
| GPS re-centering map on every fix | Only centers on first fix |
| Hospitals always showing LA area | Cache now validates location; re-fetches if moved >35 miles |
| Hospital double-display on enable | Early return after cache load prevents fetch also running |
| Digipeater cache blocking UI | Converted from requests (blocking) to NetworkFetchWorker |
NetworkFetchWorker undefined in hospital fallback |
Added _mg() lookup inside _process_hospital_data |
| APRS-IS not-connected warning in wrong log | Now appears in APRS tab preset log |
| Binary garbage from APAT81 Anytone | Truncate at first run of 3+ garbage chars |
⚠️ IGate Beta Status
IGate (both RX and TX) is still considered beta. RX IGate has been tested live on KO6IKR-5 in Los Angeles. TX IGate has had significant correctness fixes this release but needs broader field testing.
If you run IGate and find unexpected behaviour, please open a GitHub issue with your IGate log output:
https://github.com/smashingwaffle/pytnc-pro/issues
📦 Build
Remove-Item PyTNC_Pro*.spec -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force build, dist -ErrorAction SilentlyContinue
pyinstaller --onedir --windowed --icon=pytnc_pro.ico --name "PyTNC_Pro_v0.1.5-beta" `
--add-data "aprs_symbols_48;aprs_symbols_48" `
--add-data "leaflet.js;." `
--add-data "leaflet.css;." `
--add-data "aprs_map.html;." `
--add-data "tnc;tnc" `
--add-data "pytnc_pro.ico;." `
main.pyReferences
- APRS-IS IGate Design
- APRS-IS IGate Details
- WB2OSZ Understanding APRS Packets — February 2026
- WB2OSZ aprsspec repository
73 de KO6IKR
always welcome to give me feedback
KO6IKR@Gmail.com
PyTNC Pro v0.1.4-beta
PyTNC Pro — Release Notes
v0.1.4-beta
PTT Improvements
CI-V CAT PTT (Icom radios)
- New PTT method: CI-V CAT for Icom radios (IC-7100, IC-7300, IC-9700, IC-705, etc.)
- Configurable: COM port, baud rate, data bits, parity, stop bits, CI-V address (hex)
- PTT ON/OFF via standard Icom CI-V protocol (
FE FE addr E0 1C 00 01/00 FD) - Default CI-V address
88(IC-7100) — tooltip lists common addresses for other models
CM108 GPIO PTT (DigiRig Lite / USB audio-only adapters)
- New PTT method: CM108 GPIO for devices with no COM port
- Auto-detects CM108/CM119 family chips via HID scan button
- GPIO1 toggle via HID output report — Direwolf-compatible
- Requires:
pip install hidapi
PTT Method Selector
- Settings → PTT Control now has a Method dropdown:
RTS/DTR/CI-V CAT/CM108 GPIO - Switching methods shows/hides the relevant config widgets automatically
- Auto-scans CM108 devices on first selection of CM108 mode
Map Improvements
Auto-center on startup
- Map now centers on your saved location on startup (2 second delay for WebView init)
- Also centers immediately when manual location is applied or GPS fix arrives
APRS object parser fix
- Object packets (
;type) now try compressed position format first, falling back to uncompressed - Fixes objects from some IGates that were silently dropped due to compressed encoding
IGate Improvements
Duplicate suppression
- Same packet arriving via multiple digi paths is gated only once (30-second dedup window)
Callsign-exact skip rule
- Fixed: same-base-callsign stations (e.g. KO6IKR-2 on handheld) were incorrectly skipped by the IGate's own-TX filter — now matches full callsign including SSID
UI Improvements
Save Settings confirmation
- Both save buttons flash green with
✅ Saved!for 1.5 seconds on success
STOP IS darker shade
■ STOP ISbutton darkens when APRS-IS is connected, making toggle state visually clear
Clickable links in tooltips
- Popup tooltips now linkify
https://,http://, andwww.URLs in both comment and status fields - Links open in system browser via console message handler
APRS-IS
Filter uses saved location
_build_aprs_filternow correctly reads from saved lat/lon instead of falling back to hardcoded default coordinates
Version string
- APRS-IS login now identifies as
PyTNC-Pro 0.1.3
Bug Fixes
- Fixed
AttributeError: igate_rf_heardcrashingon_packetsilently after IGate deployment - Fixed
_build_vara_tabmethod eaten by bad str_replace during IGate insertion - Fixed numpy/Python version mismatch on Windows (cp312 wheels vs Python 3.14)
- Fixed PowerShell execution policy blocking venv activation
Known Limitations / Next Release
- TX IGate
_queue_rf_packetwiring pending - IGate auto-beacon fires once on enable — repeat timer not yet implemented
- Digipeater support not yet implemented
- AIS vessel data requires a separate AISHub feed (not available via APRS-IS)
v0.1.3-beta
New Features
🌐 IGate Tab
- Full RX IGate implementation (RF → Internet)
- TX IGate implementation (Internet → RF) — disabled by default
- RX IGate checkbox with green status indicator, packets-gated counter, uptime timer
- TX IGate checkbox (locked until RX is enabled), heard-window spinner, messages-only toggle
- Gated packets log with live search/filter bar, entry count, and clear button
- APRS-IS connection/disconnection events shown in IGate log on startup
- Tab order: 🗺️ MAP | 📻 APRS | 📡 VARA FM | 🌐 IGate | ℹ️ Info | ⚙️ Settings
IGate Logic
- RX gate formats packets as
SRC>DST,PATH,qAR,MYCALL:infoper APRS-IS spec - No-regate rules enforced: TCPIP, qA paths, NOGATE, RFONLY, third-party frames all skipped
- TX gate checks message-only rule and RF-heard window before gating IS packets to RF
- Auto-beacon on IGate enable: sends
I&(IGate diamond) symbol to APRS-IS
Symbol Overlay Support
- Overlay character field (A–Z, 0–9) added to APRS tab symbol picker
- Supports overlaid symbols:
I&= IGate diamond,D#= digi with D,W&= Winlink - Symbol preview updates live to show overlay letter rendered on icon
- RF and IS beacons both respect the overlay character
Map Layer Switcher (Qt toolbar)
- Street / Topo / Satellite / Dark layer selector moved to Qt toolbar
- Floating HTML
#layer-selectorremoved from map setMapLayer()JS function called from Python on combo change
Map Improvements
24-hour Station Expiry
- Stations not heard in 24 hours automatically removed from map
- Cleanup runs every 5 minutes; trail history cleaned up with marker
- 500 marker hard cap retained as safety net
Bug Fixes
- Fixed OSM/OSM-DE/Carto Leaflet layer control appearing alongside Qt layer combo
- Fixed map layer combo position (
right: 60px→right: 10px) after removing Leaflet control - Fixed font sizes in IGate tab (10–11px labels bumped to 12px for readability)
- Fixed callsign skip rule matching base callsign prefix instead of full SSID
73 de KO6IKR