- REST API: Fix id type from integer to UUID, add device/equipment
fields, correct rate limiting info (100 req/min, not "none"),
add 429 status code
- Mobile API: Fix search_callsign response field (lon not lng),
add path to packet fields, correct rate limiting/timeout docs,
clarify update_bounds behavior
- Fix flaky pipeline tests (async race on global Application config)
Implements comprehensive callsign search and live tracking:
- search_callsign: Search for callsigns with wildcard support
- "W5ISP" finds W5ISP and all SSIDs (W5ISP-1, W5ISP-9, etc.)
- "W5ISP-9" finds only that specific SSID
- "W5ISP*" finds all callsigns starting with W5ISP
- subscribe_callsign: Subscribe to live updates for a callsign
- Loads historical packets for the callsign
- Receives real-time streaming updates
- Supports wildcard patterns
- Works with or without geographic bounds
- unsubscribe_callsign: Stop tracking callsign
When both bounds and callsign are subscribed, packets are filtered
by both criteria (callsign AND within bounds).
Generated with Claude Code https://claude.com/claude-code
When mobile clients subscribe to bounds, the server now loads and sends
historical packets immediately, followed by real-time streaming packets.
This matches the web UI behavior and provides a complete view of APRS
activity in the requested area.
Optional parameters:
- limit: Max historical packets to load (default: 1000, max: 5000)
- hours_back: Hours of historical data (default: 1, max: 24)
Generated with Claude Code https://claude.com/claude-code
- Create MobileChannel for geographic bounds-based packet filtering
- Add MobileUserSocket for mobile client connections
- Implement subscribe_bounds, update_bounds, and unsubscribe events
- Leverage existing StreamingPacketsPubSub infrastructure
- Add comprehensive mobile API documentation with Swift examples
- WebSocket endpoint: wss://aprs.me/mobile/websocket
- Channel: mobile:packets
This enables iOS/Android apps to receive real-time APRS packets
filtered by geographic viewport, with efficient bandwidth usage.
- Modified get_recent_packets to not filter by has_position when tracking a specific callsign
- Ensures users can see status updates, messages, and other non-position packets
- Fixes issue where callsigns without recent position data wouldn't show any packets
- Updated documentation to reflect this behavior
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update the PostgreSQL notify_packets_insert trigger to send all necessary
fields when broadcasting new packets. Previously only minimal fields were
sent (id, sender, lat, lon, inserted_at), which prevented the info page
from displaying complete packet information during live updates.
The trigger now includes:
- Position data (lat, lon, altitude, course, speed)
- Symbol data (symbol_table_id, symbol_code)
- Device data (device_identifier, path)
- Metadata (received_at, comment, raw_packet)
- PHG data (phg_power, phg_height, phg_gain, phg_directivity)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SKIP_DB_CREATE env var to skip database creation when using PgBouncer
- Fix redis_children() to return proper child specs
- Implement zero-downtime graceful shutdown without user notifications
- Add health check plug for Kubernetes probes
- Remove user-facing shutdown notifications for seamless deployments
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces a dual-mode caching and rate limiting system that can use
either Redis (for distributed deployments) or ETS/Cachex (for single-node setups).
Key changes:
- Add Cache abstraction layer that automatically switches between Redis and Cachex
- Implement RedisCache module with full distributed cache functionality
- Implement RedisRateLimiter with sliding window algorithm for accurate rate limiting
- Add RateLimiterWrapper to provide unified API for both implementations
- Update application startup to conditionally use Redis when REDIS_URL is set
- Migrate all cache operations to use the new Cache abstraction
- Support graceful fallback to ETS-based solutions when Redis is unavailable
The system automatically detects Redis availability via REDIS_URL environment
variable and switches between implementations without code changes. This enables
proper distributed caching and rate limiting in Kubernetes deployments while
maintaining backward compatibility for development environments.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>