Staging#28
Merged
MichaelWheeley merged 15 commits intoMichaelWheeley:feature/thai-language-devfrom Mar 26, 2026
Merged
Conversation
Completes the APRS data path through the unified cloud relay:
- APRS TNC plugin emits 'aprs' events on shared pluginBus
- Cloud relay subscribes, batches APRS packets alongside decodes
- Server stores packets per session (500 max ring buffer)
- New endpoint: GET /api/rig-bridge/relay/aprs?session=&since=
Full data flow:
Direwolf/TNC → APRS TNC plugin → pluginBus → Cloud Relay
→ HTTPS push → OHC server → browser polls → APRS panel
Same pattern as WSJT-X decodes — one tunnel for everything.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New POST /api/aprs/local endpoint accepts raw APRS packets from the cloud relay, parses them with the existing parseAprsPacket(), and injects them into the aprsStations cache alongside APRS-IS data. The cloud relay state handler auto-forwards APRS packets to this endpoint on arrival, so they appear in the APRS panel without any frontend changes — useAPRS polls /api/aprs/stations which now returns both internet (APRS-IS) and local RF (TNC) stations merged together. Local stations are tagged with source: 'local-tnc' for UI distinction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes sluggish frequency updates, false connection loss, and unreliable PTT in cloud relay mode. Changes: - state.js: new onStateChange() listener hook - Cloud relay pushes immediately on any state change (100ms debounce) instead of waiting for the 2s interval timer - Interval timer still runs as fallback for batched data (decodes, APRS) - Browser polls every 1s instead of 2s - relayActive timeout increased from 15s to 30s to prevent false disconnections during network jitter Before: worst case 4s latency (2s push interval + 2s poll interval) After: ~200ms for state changes (100ms debounce + 100ms poll offset) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the 24-hour ITURHFProp fetch failed but the single-hour fetch succeeded, the bars used ITURHFProp data while the chart used the built-in fallback calculation — two different models producing different reliability values for the same band at the same hour. Fix: pre-seed the predictions array with the ITURHFProp single-hour values before the fallback fills in the remaining 23 hours. The fallback now preserves pre-seeded hours instead of overwriting them, so the chart's current-hour cell always matches the bars. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CARTO and Google tile providers render labels in the browser's Accept-Language locale. Users with CJK languages configured (even as secondary) would see Chinese/Japanese country names on the map. Added language=en to CARTO Dark and Streets tile URLs, and hl=en to Google Hybrid. Esri tiles already render in English by default. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced hardcoded language=en with {lang} placeholder in CARTO and
Google tile URLs. WorldMap and AzimuthalMap resolve {lang} from the
i18n language at tile creation time.
German users see German labels, Japanese users see Japanese, etc.
Matches the language selected in OHC settings, not the browser's
random Accept-Language header that was causing CJK labels for some
European users.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parses APRS addressed messages and bulletins alongside position
packets. Detects shelter-related content via keyword matching
(shelter, evacuate, beds, capacity, etc.) and resource tokens.
- parseAprsMessage() handles :ADDRESSEE:message{id format
- Bulletins (BLN*) captured for area-wide alerts
- Shelter reports flagged with isShelterReport for EmComm dashboard
- Messages stored in ring buffer (200 max)
- Both APRS-IS and local TNC packets parsed for messages
New endpoints:
- GET /api/aprs/messages?since=&shelter=true
- GET /api/aprs/shelters — shelter reports only with resource tokens
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…829) - APRS symbol-to-icon mapping: 30+ symbols mapped to appropriate icons (EOC, shelter, mobile, fixed, weather, digipeater, etc.) - getStationType() classifies stations as mobile/fixed/unknown - Station popups show icon, type label, and RF tag for local TNC stations - Sidebar station list shows icons and green "RF" badge for local sources - APRS source selector dropdown: All Sources / RF Only / Internet Only Filters displayed stations by source (local-tnc vs APRS-IS) - PanelSection component accepts 'extra' prop for inline controls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 3: Net Operations - Net check-in/check-out via APRS messages to EMCOMM - CQ NETNAME <status> → check in with status message - U NETNAME → check out - Operator status board panel in EmComm sidebar: - Callsign, net name, status, last heard age - Green (active) / yellow (stale >10min) border indicators - Resource tokens from APRS beacons - MSG button to open message compose - Manual check-in/out endpoints for operators without APRS TX - GET /api/aprs/net — net roster with live station data merge Phase 4: Messaging - Message compose UI in EmComm sidebar - Opens from MSG button on net roster or station click - 67-char limit with counter - Send via Enter key or Send button - POST /api/aprs/message — proxies to rig-bridge APRS TNC plugin - Messages sent over RF via local TNC (no internet required) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…QNS) (#829) Parses APRS telemetry frames for sensor data from weather stations, battery monitors, flood gauges, and other IoT devices: - T#seq,v1,v2,v3,v4,v5,bits — 5 analog channels + 8 digital bits - PARM messages — define parameter names (e.g. "Temp,Batt,Wind") - UNIT messages — define units (e.g. "degF,V,mph") - EQNS messages — coefficient equations (a*x²+b*x+c) for calibration Parsed from both APRS-IS and local TNC packets. Stored per-callsign with computed values when equations are defined. New endpoint: GET /api/aprs/telemetry?callsign=optional Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version bump to 26.2.1 with comprehensive WhatsNew changelog: - Rig Bridge: 22 plugins, plugin manager UI, cloud relay - Bidirectional digital modes (WSJT-X/MSHV/JTDX/JS8Call) - EmComm: net operations, APRS messaging, telemetry - RBN spotter mode - Propagation bars/chart fix - Locale-aware map labels - CORS fix for rig control Rig Bridge bumped to v2.0.0. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace || and ! falsy checks with nullish-safe alternatives throughout the codebase so that stations on the equator (lat=0) or prime meridian (lon=0) are handled correctly instead of being treated as missing values. - Use Number.isFinite() in server/config.js to distinguish NaN (unset env var) from a valid 0 - Replace || with ?? in src/utils/config.js and useSatelliteLayer.js - Use decode.lat == null in wsjtx.js (3 locations) instead of !decode.lat - Use ?? null in aprs.js net-roster entries instead of || null - Replace !lat || !lon guards with lat == null || lon == null in useLightning.js, useEarthquakes.js, useActiveUsers.js, EmcommLayout.jsx, useEmcommData.js, and usePOTASpots.js - Fix usePOTASpots.js coordinate init to use != null instead of truthiness - Replace || 0 with ?? 0 in AzimuthalMap.jsx and SettingsPanel.jsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: correct falsy checks for zero lat/lon coordinates
Trailing newlines in GitHub comment bodies caused exact-match checks to silently fail, skipping the assignment/close step. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite emcomm-roadmap.md as a feature guide (all 6 phases shipped) - Add net operations, APRS messaging, source selector, telemetry docs - Document Winlink gateway plugin status (built, waiting on API key) - Expand README EmComm section with full feature coverage - Update ROADMAP.md to v26.2.1, remove resolved issues, update status Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Type of change
How to test
Checklist
server.js: caches have TTLs and size caps (we serve 2,000+ concurrent users)var(--accent-cyan), etc.).bak,.old,console.logdebug lines, or test scripts includedScreenshots (if visual change)