Skip to main content

Documentation Index

Fetch the complete documentation index at: https://crsdk.app/llms.txt

Use this file to discover all available pages before exploring further.

The Client SDK has two separate event categories that serve different purposes and are subscribed to differently.
CategorySourcePurpose
Connection eventsmanager.on()Camera discovery and connection state
Property & action eventsmanager.camera(id).eventsCamera settings changes, warnings, transfers

Connection Events

Emitted by CameraManager (both server and browser variants). Use these to monitor camera discovery, connection state, and errors.

Events table

EventPayloadWhen
camera-found{ camera }New camera detected by polling
camera-lost{ camera }Camera no longer detected (unplugged/offline)
camera-connecting{ cameraId }Connection attempt started
camera-ready{ cameraId, camera }Connected and ready for commands
camera-disconnected{ cameraId, error? }Disconnected (explicit or unexpected)
connection-failed{ cameraId, error, attempt }Connection attempt failed
error{ message }Manager-level error (poll failure, SSE error)

Subscribing

manager.on('camera-found', ({ camera }) => {
  console.log(`Discovered ${camera.model} (${camera.id})`);
});

manager.on('camera-ready', ({ cameraId, camera }) => {
  console.log(`${camera.model} ready for commands`);
});

manager.on('camera-disconnected', ({ cameraId, error }) => {
  if (error) {
    console.log(`Unexpected disconnect: ${error}`);
  } else {
    console.log('Clean disconnect');
  }
});

manager.on('connection-failed', ({ cameraId, error, attempt }) => {
  console.log(`Attempt ${attempt} failed: ${error}`);
});

manager.on('error', ({ message }) => {
  console.error('Manager error:', message);
});

Unsubscribing

// Remove a specific listener
const handler = ({ cameraId }) => console.log('ready', cameraId);
manager.on('camera-ready', handler);
manager.off('camera-ready', handler);

// Remove all listeners for an event
manager.off('camera-ready');

One-shot listeners

// Auto-removed after the first fire
manager.on('camera-ready', async ({ cameraId }) => {
  // runs only once for the first camera that connects
});

Property & Action Events

Real-time notifications from the camera via SSE. Use manager.camera(id).events to subscribe to property changes, warnings, autofocus status, file transfers, and errors.

Events table

EventPayloadWhen
connected{ cameraId }Camera connection established (SSE callback from server)
disconnected{ error }Camera disconnected (SSE callback from server)
propertyChanged{ codes }Camera settings changed (ISO, aperture, etc.)
warning{ code }Camera warning (code 0x20011 = photo captured)
afStatus{ state }Autofocus state changed ('focused' | 'unlocked' | 'tracking')
downloadComplete{ filename }File saved to host PC
transferProgress{ percent, filename }File transfer progress
error{ code }SSE connection error
closeSSE stream closed by manager
The simplest way to subscribe to per-camera events is via manager.camera(id).events:
manager.on('camera-ready', ({ cameraId }) => {
  const cam = manager.camera(cameraId);

  cam.events.on('propertyChanged', (data) => {
    console.log('Properties changed:', data.codes);
  });

  cam.events.on('warning', (data) => {
    if (data.code === '0x20011') console.log('Photo captured!');
  });

  cam.events.on('downloadComplete', (data) => {
    console.log('File saved:', data.filename);
  });

  cam.events.on('afStatus', (data) => {
    console.log('AF state:', data.state);
  });

  cam.events.on('transferProgress', (data) => {
    console.log(`Transfer: ${data.percent}%`, data.filename);
  });

  // One-shot listener — auto-removed after first fire
  cam.events.once('connected', () => {
    console.log('First connection established');
  });
});

Via EventStream directly

For manual control, create an EventStream directly:
import { EventStream } from 'camera-remote-web-api';

// All cameras
const events = new EventStream('http://localhost:8080');

// Or filter to a single camera
const camEvents = new EventStream('http://localhost:8080', 'D10F60149B0C');

camEvents.on('propertyChanged', (data) => {
  console.log('Properties changed:', data.codes);
});

Cleanup

// Remove specific callback
const handler = (data) => console.log(data);
events.on('downloadComplete', handler);
events.off('downloadComplete', handler);

// Close SSE connection
events.close();

Using Both Together

Connection events tell you when a camera is ready. Property & action events tell you what’s happening on the camera.
import { CameraManager } from 'camera-remote-web-api/server';

const manager = new CameraManager({ port: 8080, connectionMode: 'remote-transfer' });

// Connection events — monitor lifecycle
manager.on('camera-ready', async ({ cameraId, camera }) => {
  console.log(`${camera.model} connected`);
  const cam = manager.camera(cameraId);

  // Property events — monitor camera activity
  cam.events.on('downloadComplete', (data) => {
    console.log(`${camera.model}: file saved — ${data.filename}`);
  });

  cam.events.on('propertyChanged', (data) => {
    console.log(`${camera.model}: settings changed — ${data.codes}`);
  });
});

await manager.start();