Skip to main content

Socket Handling

Use EOISocketClient when you want real-time stream, live-search, count, performance, or video-processing updates from EyesOnIt instead of polling REST endpoints.

Imports

Import the socket client, room helpers, and message types from the package root.

import {
EOISocketClient,
EOISocketRooms,
EOISocketRoomNames,
type EOISocketClientOptions,
type EOISocketEventHandlers,
} from "eyesonit-typescript-sdk";

Create A Socket Client

Create the client with an EOISocketClientOptions object:

const socket = new EOISocketClient({
apiBaseUrl: "http://localhost:8000",
autoJoinRooms: [
EOISocketRooms.allStreamDetections,
EOISocketRooms.allPerformanceUpdates,
],
handlers: {
handleConnect() {
console.log("Connected", socket.getClientId());
},
handleDisconnect(reason) {
console.log("Disconnected", reason);
},
handleStreamDetection(message) {
console.log(message.room, message.detections.length);
},
},
});

EOISocketClient does not connect in the constructor. The SDK creates the underlying Socket.IO client with autoConnect: false, so call await socket.connect() when you are ready to open the connection.

Constructor Options

OptionTypeDescription
apiBaseUrlstringBase URL for the EyesOnIt server, such as http://localhost:8000
pathstringOptional Socket.IO path. Defaults to /websocket
clientIdstringOptional client identifier. If omitted, the SDK generates one unless useClientIdQueryParam is false
useClientIdQueryParambooleanWhen omitted or true, the SDK sends client_id in the Socket.IO query string
autoJoinRoomsstring[]Rooms to remember immediately and subscribe to as soon as the socket connects
handlersEOISocketEventHandlersOptional grouped handlers for connect, disconnect, and server messages
socketOptionsPartial<ManagerOptions & SocketOptions>Additional socket.io-client options passed through to io(...)

Notes:

  • socketOptions.query can be a query-string or object. The SDK merges client_id into it when client IDs are enabled.
  • getClientId() returns the resolved client ID, or undefined when useClientIdQueryParam is false.

Connection And Disconnection

Typical flow:

  1. Create EOISocketClient.
  2. Register handlers, either in the constructor or with setter methods.
  3. Join rooms directly or provide autoJoinRooms.
  4. Call await connect().
  5. Process incoming messages.
  6. Call leaveRoom(...) and disconnect() when you are done.

Example:

import {
EOISocketClient,
EOISocketRooms,
} from "eyesonit-typescript-sdk";

const socket = new EOISocketClient({
apiBaseUrl: "http://localhost:8000",
});

socket.onceConnect(() => {
console.log("Connected once");
});

socket.onDisconnect((reason) => {
console.log("Socket.IO disconnected:", reason);
});

socket.joinRoom(EOISocketRooms.allStreamUpdates);
socket.joinRoom(EOISocketRooms.allCountUpdates);

try {
await socket.connect();
} catch (error) {
console.error("Connection failed", error);
}

Connection behavior:

  • connect() resolves when the Socket.IO connect event fires.
  • connect() rejects if the initial connection fails with connect_error.
  • disconnect() closes the active connection if one exists.
  • isConnected() reports the current socket state.
  • The SDK remembers joined rooms and automatically re-subscribes to them after reconnecting.

Handlers

You can register handlers in two ways:

  • Pass a handlers object to the constructor.
  • Call setHandlers(...) or the individual setter methods later.

Supported handler properties are:

interface EOISocketEventHandlers {
handleConnect?(): void;
handleDisconnect?(reason: string): void;
handleStreamUpdate?(message: EOIStreamUpdateMessage): void;
handleStreamDetection?(message: EOIStreamDetectionMessage): void;
handlePerformanceUpdate?(message: EOIPerformanceUpdateMessage): void;
handleLiveSearchDetection?(message: EOILiveSearchDetectionMessage): void;
handleCountUpdate?(message: EOICountUpdateMessage): void;
handleVideoProcessingUpdate?(message: EOIVideoProcessingUpdateMessage): void;
}

The setter methods are:

  • setConnectHandler(...)
  • setDisconnectHandler(...)
  • setStreamUpdateHandler(...)
  • setStreamDetectionHandler(...)
  • setPerformanceUpdateHandler(...)
  • setLiveSearchDetectionHandler(...)
  • setCountUpdateHandler(...)
  • setVideoProcessingUpdateHandler(...)

Use setHandlers(null) or pass null to an individual setter to remove handlers.

Rooms And Subscriptions

The SDK exports the built-in room names used by the EyesOnIt socket server:

ConstantRoom NameTypical Message Type
EOISocketRooms.allStreamUpdatesall_stream_updatesstream_update
EOISocketRooms.allStreamDetectionsall_stream_detectionsstream_detection
EOISocketRooms.allPerformanceUpdatesall_performance_updatesperformance_update
EOISocketRooms.liveSearchDetectionslive_search_detectionsbase prefix for live-search detection rooms
EOISocketRooms.allCountUpdatesall_count_updatescount_update
EOISocketRooms.allVideoProcessingUpdatesall_video_processing_updatesvideo_processing_update

Room helpers:

  • joinRoom(room) stores the room locally and sends subscribe immediately if already connected.
  • joinRooms(rooms) joins multiple rooms.
  • leaveRoom(room) removes the room locally and sends unsubscribe if connected.
  • joinLiveSearchDetections(searchId) joins live_search_detections_${searchId} and returns that room name.
  • EOISocketRooms.liveSearchDetectionsForSearch(searchId) builds the same live-search room name without joining it.

Event And Message Types

The socket client listens for these server events:

Server EventHandlerMessage Type
stream_updatehandleStreamUpdateEOIStreamUpdateMessage
stream_detectionhandleStreamDetectionEOIStreamDetectionMessage
performance_updatehandlePerformanceUpdateEOIPerformanceUpdateMessage
live_search_detectionhandleLiveSearchDetectionEOILiveSearchDetectionMessage
count_updatehandleCountUpdateEOICountUpdateMessage
video_processing_updatehandleVideoProcessingUpdateEOIVideoProcessingUpdateMessage

room is optional on all message wrappers because the server can emit either (room, payload) or just (payload). Every wrapper also includes rawPayload so you can inspect the original server message.

EOIStreamUpdateMessage

interface EOIStreamUpdateMessage {
room?: string;
streamInfos: EOIStreamInfo[];
rawPayload: unknown;
}

Parsing behavior:

  • If the payload is an array, the SDK treats it as the stream list.
  • Otherwise it looks for a streams array on the payload object.
  • Each entry is parsed into EOIStreamInfo.

EOIStreamInfo commonly includes:

  • stream_url
  • stream_id
  • name
  • status
  • frame_rate
  • index_for_search
  • search_index_types
  • regions
  • lines
  • notification
  • recording

EOIStreamDetectionMessage

interface EOIStreamDetectionMessage {
room?: string;
detections: EOIVideoDetection[];
image?: string | null;
rawPayload: unknown;
}

Parsing behavior:

  • The SDK reads payload.detections.
  • Each entry is parsed into EOIVideoDetection.
  • image is copied from payload.image when present.

EOIVideoDetection commonly includes:

  • region
  • class_name
  • stream_url
  • stream_name
  • event
  • time
  • frame_num
  • object_description
  • condition
  • result_id
  • image

Use detection.getDetectedObjects() and detection.getMaxConfidenceDescription() to work with the nested detection objects in condition.

EOILiveSearchDetectionMessage

EOILiveSearchDetectionMessage has the same shape as EOIStreamDetectionMessage:

interface EOILiveSearchDetectionMessage {
room?: string;
detections: EOIVideoDetection[];
image?: string | null;
rawPayload: unknown;
}

Use this handler for detections published to live-search rooms, usually after joining a room such as live_search_detections_<searchId>.

EOIPerformanceUpdateMessage

interface EOIPerformanceUpdateMessage<T = unknown> {
room?: string;
data: T;
rawPayload: T;
}

Parsing behavior:

  • The SDK does not transform performance payloads.
  • data and rawPayload are the original payload object.
  • Narrow or cast T in application code if your deployment uses a known performance schema.

EOICountUpdateMessage

interface EOICountUpdateMessage {
room?: string;
count: EOICountData | null;
rawPayload: unknown;
}
interface EOICountData {
frame_number?: number | null;
time?: number | string | null;
count?: number | null;
[key: string]: unknown;
}

Parsing behavior:

  • If the payload contains a nested count object, that object is used.
  • Otherwise the payload object itself is treated as the count message.
  • Non-object payloads become count: null.

EOIVideoProcessingUpdateMessage

interface EOIVideoProcessingUpdateMessage {
room?: string;
updates: EOIVideoProcessingUpdate[];
isSnapshot: boolean;
rawPayload: unknown;
}
interface EOIVideoProcessingUpdate {
video_id: string | number;
input_video_path?: string | null;
input_video_name?: string | null;
length?: number | null;
current_processing_time?: number | null;
percent_complete?: number | null;
}

Parsing behavior:

  • If the payload is an array, the SDK treats it as a snapshot and sets isSnapshot to true.
  • If the payload is a single object, the SDK wraps it as one update and sets isSnapshot to false.
  • Only object entries are kept in updates.

Complete Example

import {
EOISocketClient,
EOISocketRooms,
} from "eyesonit-typescript-sdk";

const socket = new EOISocketClient({
apiBaseUrl: "http://localhost:8000",
autoJoinRooms: [
EOISocketRooms.allStreamDetections,
EOISocketRooms.allVideoProcessingUpdates,
],
handlers: {
handleConnect() {
console.log("Connected");
},
handleDisconnect(reason) {
console.log("Disconnected", reason);
},
handleStreamDetection(message) {
for (const detection of message.detections) {
console.log(detection.stream_name, detection.event, detection.time?.toISO());
}
},
handleVideoProcessingUpdate(message) {
console.log(message.isSnapshot ? "snapshot" : "delta", message.updates);
},
},
});

const liveSearchRoom = socket.joinLiveSearchDetections(42);
console.log("Joined room", liveSearchRoom);

await socket.connect();