Skip to main content

Overview

The /ws/simulation WebSocket channel enables real-time streaming of surgical telemetry data from Unity-based surgical simulations to the Justina backend. Surgeons connect to this channel to transmit movement coordinates, surgical events, and timestamps during active simulation sessions.

Connection

Endpoint

ws://localhost:8080/ws/simulation?token=<jwt-token>

Authentication

Requires a valid JWT token with ROLE_SURGEON (or ROLE_CIRUJANO). AI accounts cannot connect to this channel.

Connection Example

const token = localStorage.getItem('jwt_token');
const ws = new WebSocket(`ws://localhost:8080/ws/simulation?token=${token}`);

ws.onopen = () => {
  console.log('🔗 Connected to simulation channel');
};

ws.onerror = (error) => {
  console.error('❌ Connection error:', error);
};

ws.onclose = (event) => {
  console.log(`🔌 Disconnected: ${event.code} - ${event.reason}`);
};

ws.onmessage = (event) => {
  const response = JSON.parse(event.data);
  console.log('📨 Server response:', response);
};

Message Protocol

Client → Server: Telemetry Data

Clients send surgical telemetry messages in JSON format:
coordinates
double[]
required
3D coordinates of the surgical instrument
  • Array length: 2 or 3 elements
  • Format: [x, y, z] or [x, y]
  • Example: [10.5, 20.3, 15.7]
event
SurgeryEvent
required
Type of surgical event occurringValid values:
  • START - Surgery session begins
  • NONE - Normal movement, no special event
  • TUMOR_TOUCH - Instrument touched tumor
  • HEMORRHAGE - Hemorrhage occurred
  • FINISH - Surgery session ends
timestamp
long
required
Unix timestamp in milliseconds
  • Must be a positive number
  • Example: 1709636400000

Telemetry Message Examples

{
  "coordinates": [10.5, 20.3, 15.7],
  "event": "START",
  "timestamp": 1709636400000
}

Server → Client: Completion Response

When a surgery is finished (FINISH event received), the server responds with:
status
string
Operation status, always "SAVED" on success
surgeryId
UUID
Unique identifier of the saved surgery session
Surgery Saved Response
{
  "status": "SAVED",
  "surgeryId": "550e8400-e29b-41d4-a716-446655440000"
}
The server only sends a response after receiving a FINISH event. All other telemetry messages are acknowledged silently.

Complete Workflow Example

1

Surgeon Authenticates

Surgeon logs in and receives JWT token
2

Connect to WebSocket

Establish WebSocket connection with token parameter
3

Start Surgery

Send START event with initial coordinates
4

Stream Movements

Continuously send telemetry data during surgery
  • Send coordinates at regular intervals (e.g., 60 FPS)
  • Include appropriate event types when they occur
5

End Surgery

Send FINISH event with final coordinates
6

Receive Confirmation

Server responds with SAVED status and surgery ID
7

AI Notification

Backend automatically notifies AI systems via /ws/ai channel

Full Implementation Example

class SurgerySimulation {
  constructor(token) {
    this.ws = new WebSocket(`ws://localhost:8080/ws/simulation?token=${token}`);
    this.setupHandlers();
  }

  setupHandlers() {
    this.ws.onopen = () => {
      console.log('✅ Connected');
      this.startSurgery();
    };

    this.ws.onmessage = (event) => {
      const response = JSON.parse(event.data);
      if (response.status === 'SAVED') {
        console.log(`✅ Surgery saved: ${response.surgeryId}`);
        this.ws.close();
      }
    };
  }

  startSurgery() {
    this.sendTelemetry([0, 0, 0], 'START');
  }

  sendTelemetry(coordinates, event = 'NONE') {
    const message = {
      coordinates: coordinates,
      event: event,
      timestamp: Date.now()
    };
    this.ws.send(JSON.stringify(message));
  }

  finishSurgery(finalCoords) {
    this.sendTelemetry(finalCoords, 'FINISH');
  }
}

// Usage
const simulation = new SurgerySimulation('your-jwt-token');

// During surgery loop
setInterval(() => {
  const coords = [Math.random() * 100, Math.random() * 100, Math.random() * 100];
  simulation.sendTelemetry(coords, 'NONE');
}, 100); // 10 FPS

// End surgery after 5 seconds
setTimeout(() => {
  simulation.finishSurgery([50, 50, 50]);
}, 5000);

Error Handling

Validation Errors

If the telemetry message fails validation, the connection is closed with 1003 BAD_DATA:
ws.onclose = (event) => {
  if (event.code === 1003) {
    console.error('❌ Invalid message format');
    // Common issues:
    // - Missing required fields
    // - Invalid event type
    // - Negative timestamp
    // - Coordinates array wrong size
  }
};
Validation rules:
  • coordinates must be an array of 2 or 3 doubles
  • event must be a valid SurgeryEvent enum value
  • timestamp must be a positive number

Authentication Errors

Invalid or missing token results in 1008 POLICY_VIOLATION:
ws.onclose = (event) => {
  if (event.code === 1008) {
    console.error('❌ Authentication failed');
    // Redirect to login to get new token
    window.location.href = '/login';
  }
};

Backend Processing

The backend performs these actions on telemetry receipt:
1

Parse JSON

Deserialize incoming message to TelemetryDTO
2

Validate Data

Check all validation constraints
3

Extract User ID

Retrieve surgeon ID from WebSocket session attributes
4

Create/Update Session

Get or create SurgerySession object for this connection
5

Record Movement

Add movement to session’s trajectory list
6

Check for FINISH

If FINISH event:
  • Mark surgery as ended
  • Persist to database
  • Generate surgery ID
  • Send confirmation to client
  • Notify AI systems

Session Management

Each WebSocket connection maintains an in-memory SurgerySession object:
  • Session Creation: First message creates new session
  • Movement Accumulation: All movements stored in session
  • Session Persistence: FINISH event triggers database save
  • Session Cleanup: Session removed from memory after save
If a surgeon disconnects before sending FINISH, the session data is lost and not persisted to the database.

Performance Considerations

Message Frequency

Recommended telemetry transmission rates:
  • High precision: 60 messages/second (60 FPS)
  • Standard: 30 messages/second (30 FPS)
  • Low bandwidth: 10 messages/second (10 FPS)

Connection Limits

  • One active simulation session per surgeon
  • Multiple connections with same token create separate sessions

Message Size

Typical telemetry message size: ~100 bytes Estimated bandwidth:
  • 60 FPS: ~6 KB/s upload
  • 30 FPS: ~3 KB/s upload
  • 10 FPS: ~1 KB/s upload

Next Steps

AI Channel

Learn how AI systems receive surgery notifications

Surgery Endpoints

Access saved trajectory data via REST API

Build docs developers (and LLMs) love