Menu
WebSocket and real-time streaming architecture
Version: 1.1
Created: 2026-01-16
Updated: 2026-01-16
Status: ✅ COMPLETE (Deployed to Production)
Phase 2 implements real-time WebSocket distribution of flight data changes to connected clients. This enables applications like CRC, vNAS, SimAware, and vPilot to receive instant updates rather than polling the REST API.
PHP Ratchet was selected because:
| Component | File | Status |
|---|---|---|
| WebSocket Server | scripts/swim_ws_server.php |
✅ Deployed |
| Event Detection | scripts/swim_ws_events.php |
✅ Deployed |
| ADL Daemon Integration | scripts/vatsim_adl_daemon.php |
✅ Deployed |
| JavaScript Client | api/swim/v1/ws/swim-ws-client.js |
✅ Deployed |
| Apache Proxy Config | scripts/startup.sh |
✅ Deployed |
wss://perti.vatcscc.org/api/swim/v1/ws (via Apache proxy)┌─────────────────────────────────────────────────────────────────────────────┐
│ PERTI Azure App Service │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────┐ ┌───────────────────────────────────────┐ │
│ │ vatsim_adl_daemon │ │ swim_ws_server.php │ │
│ │ (15s refresh) │ │ (Ratchet on port 8090) │ │
│ └─────────┬─────────┘ │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │
│ │ 1. After refresh │ │ Connected Clients │ │ │
│ │ detect changes │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │
│ │ │ │ │ CRC │ │vNAS │ │SimAw│ ... │ │ │
│ ▼ │ │ └──┬──┘ └──┬──┘ └──┬──┘ │ │ │
│ ┌───────────────────┐ │ │ │ │ │ │ │ │
│ │ swim_ws_events.php│ │ └─────┼───────┼───────┼───────────┘ │ │
│ │ (Event Detection) │ │ │ │ │ │ │
│ └─────────┬─────────┘ │ │ 3. Push filtered events │ │
│ │ │ ▼ │ │
│ │ 2. Write to │ ┌─────────────────────────────────┐ │ │
│ │ event file │ │ Subscription Filter │ │ │
│ ▼ │ │ - By airport │ │ │
│ ┌───────────────────┐ │ │ - By ARTCC │ │ │
│ │/tmp/swim_ws_ │────────▶│ │ - By callsign prefix │ │ │
│ │events.json │ │ │ - By bounding box │ │ │
│ └───────────────────┘ │ └─────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────┘ │
│ │
│ ┌───────────────────┐ │
│ │ Apache (port 80) │ ─── ProxyPass /api/swim/v1/ws ──▶ ws://127.0.0.1:8090│
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
| Event | Trigger | Payload |
|---|---|---|
flight.created |
New flight filed | callsign, dep, arr, equipment, route, position |
flight.departed |
OFF time detected | callsign, dep, arr, off_utc |
flight.arrived |
IN time detected | callsign, dep, arr, in_utc |
flight.deleted |
Pilot disconnected | callsign, flight_uid |
flight.positions |
Position batch (optional) | Array of all position updates |
| Event | Trigger | Payload |
|---|---|---|
tmi.issued |
New GS/GDP created | program_type, airport, times, reason |
tmi.released |
TMI ended/purged | program_id, status, end_time |
wss://perti.vatcscc.org/api/swim/v1/ws?api_key=YOUR_KEY
{
"action": "subscribe",
"channels": ["flight.created", "flight.departed", "tmi.*"],
"filters": {
"airports": ["KJFK", "KEWR"],
"artccs": ["ZNY"],
"callsign_prefix": ["AAL"],
"bbox": {"north": 42, "south": 40, "east": -72, "west": -75}
}
}
{
"type": "flight.departed",
"timestamp": "2026-01-16T14:30:15.123Z",
"data": {
"callsign": "UAL123",
"flight_uid": "abc123",
"dep": "KEWR",
"arr": "KSFO",
"off_utc": "2026-01-16T14:30:00Z"
}
}
// WebSocket real-time events
'websocket_enabled' => true,
'websocket_positions' => false, // High volume - disabled by default
$config = [
'host' => '0.0.0.0',
'port' => 8090,
'auth_enabled' => true,
'event_file' => '/tmp/swim_ws_events.json',
];
| Log | Location |
|---|---|
| WebSocket Server | /home/LogFiles/swim_ws.log |
| ADL Daemon | /home/LogFiles/vatsim_adl.log |
ws_events count:[2026-01-16 07:02:27Z] [INFO] Refresh #5 {"pilots":756,"sp_ms":4892,"ws_events":6}
No additional costs - WebSocket server runs on existing Azure App Service ($5/month SWIM_API database unchanged).