Skip to content

Staging#28

Merged
MichaelWheeley merged 15 commits intoMichaelWheeley:feature/thai-language-devfrom
accius:Staging
Mar 26, 2026
Merged

Staging#28
MichaelWheeley merged 15 commits intoMichaelWheeley:feature/thai-language-devfrom
accius:Staging

Conversation

@MichaelWheeley
Copy link
Copy Markdown
Owner

What does this PR do?

Type of change

  • Bug fix
  • New feature
  • Performance improvement
  • Refactor / code cleanup
  • Documentation
  • Translation
  • Map layer plugin

How to test

Checklist

  • App loads without console errors
  • Tested in Dark, Light, and Retro themes
  • Responsive at different screen sizes (desktop + mobile)
  • If touching server.js: caches have TTLs and size caps (we serve 2,000+ concurrent users)
  • If adding an API route: includes caching and error handling
  • If adding a panel: wired into Modern, Classic, and Dockable layouts
  • No hardcoded colors — uses CSS variables (var(--accent-cyan), etc.)
  • No .bak, .old, console.log debug lines, or test scripts included

Screenshots (if visual change)

accius and others added 15 commits March 25, 2026 18:59
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>
@MichaelWheeley MichaelWheeley merged commit f8c1e3b into MichaelWheeley:feature/thai-language-dev Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants