API Reference

BlueOS Extension API

blueos-extension (:8099)

HTTP Endpoints

GET /health

Health check endpoint.

Response:

{
  "status": "healthy",
  "serial": true,
  "frames": 12345,
  "protocol": "binary_v4"
}

GET /api/latest

Get latest sensor frame (JSON).

Response: Full sensor frame (see Architecture → JSON frame output)

GET /api/dvl

Get DVL (Doppler Velocity Log) state.

Response:

{
  "vx": 0.0,
  "vy": 0.0,
  "vz": 0.0,
  "valid": false
}

GET /api/ctd

Get CTD data (Conductivity, Temperature, Depth).

Response:

{
  "timestamp": "2026-03-27T17:00:00",
  "depth_m": 5.2,
  "temperature_c": 15.3,
  "conductivity_us": 42000.0,
  "salinity_psu": 35.5,
  "sound_velocity_ms": 1485.7,
  "pressure_mbar": 1520.0
}

GET /api/status

System status and statistics.

Response:

{
  "frames": 12345,
  "clients": 2,
  "port": "/dev/ttyUSB0",
  "serial_connected": true,
  "log": "/app/logs/session_20260327_170000.jsonl",
  "ws_port": 8766,
  "crc_errors": 3,
  "protocol": "binary_v4",
  "udp_targets": ["127.0.0.1"],
  "mavlink_enabled": true,
  "mavlink_target": "192.168.2.2:14401",
  "mavlink_sent": 5432
}

WebSocket (port 8766)

Real-time sensor frames (JSON), published at ~2Hz.

Message format: Same as /api/latest response.

Example client (JavaScript):

const ws = new WebSocket('ws://192.168.0.174:8766');
ws.onmessage = (event) => {
    const frame = JSON.parse(event.data);
    console.log('IMU:', frame.imu);
    console.log('Depth:', frame.depth);
};

UDP Forwarding

  • Port 14555: Kogger A raw BB55 frames

  • Port 14556: Kogger B raw BB55 frames

Target: Kogger App desktop viewer

Kogger Viewer API

kogger-viewer (:8100)

HTTP Endpoints

GET /health

Health check.

Response:

{
  "status": "healthy",
  "a_packets": 1234,
  "a_bytes": 123456,
  "a_bb55": 1200,
  "a_pings": 150,
  "b_packets": 1150,
  "b_bytes": 115000,
  "b_bb55": 1100,
  "b_pings": 140
}

GET /api/status

Detailed stats.

Response:

{
  "a_packets": 1234,
  "a_bytes": 123456,
  "a_bb55": 1200,
  "a_pings": 150,
  "b_packets": 1150,
  "b_bytes": 115000,
  "b_bb55": 1100,
  "b_pings": 140,
  "clients": 1,
  "ws_port": 8101
}

POST /api/kogger_cmd

Forward Kogger command to ESP32 → Kogger device.

Request:

{
  "port": 14570,
  "data": "base64_encoded_bb55_command"
}

Response:

{
  "status": "ok",
  "port": 14570,
  "bytes": 42
}

WebSocket (port 8101)

Real-time waterfall ping data.

Message format:

{
  "ch": "A",
  "amp": "base64_encoded_amplitude_200_bytes",
  "n": 1234
}

Fields:

  • ch: Channel (“A” or “B”)

  • amp: Base64-encoded 200-byte amplitude array

  • n: Ping sequence number

Example client (JavaScript):

const ws = new WebSocket('ws://192.168.0.174:8101');
ws.onmessage = (event) => {
    const ping = JSON.parse(event.data);
    const ampData = atob(ping.amp); // decode base64
    // Render waterfall line...
};

Environment Variables

blueos-extension

Variable

Default

Description

SERIAL_PORT

/dev/ttyUSB0

ESP32 serial port

BAUD

115200

Serial baud rate

WS_PORT

8766

WebSocket port

HTTP_PORT

8099

HTTP server port

UDP_TARGETS

127.0.0.1

Comma-separated Kogger UDP targets

MAVLINK_ENABLED

1

Enable MAVLink bridge (0/1)

MAVLINK_TARGET

192.168.2.2

MAVLink destination IP

MAVLINK_PORT

14401

MAVLink destination port

CTD_PUSH_URL

(empty)

External CTD logger URL

kogger-viewer

Variable

Default

Description

HTTP_PORT

8100

HTTP server port

WS_PORT

8101

WebSocket port

UDP_PORT_A

14555

Kogger A UDP listen port

UDP_PORT_B

14556

Kogger B UDP listen port

Data Logging

JSONL Log Format

Location: /app/logs/session_YYYYMMDD_HHMMSS.jsonl

Each line is a JSON sensor frame with added timestamp:

{
  "_t": "2026-03-27T17:00:00.123456",
  "ts": 12345,
  "imu": {...},
  "gps": {...},
  "depth": {...},
  "...": "..."
}

Log Rotation

  • New log file created on service restart

  • No automatic rotation (manual cleanup recommended)

  • Logs persisted to /usr/blueos/extensions/slam-hub on host