Insolitum Developers
Guides

Real-time Events

Subscribe to NATS events via WebSocket. Telemetry data, alerts, module-to-module communication, and custom events.

Real-time Events

Insolitum Universe uses NATS as its event bus. Modules connect via a WebSocket gateway that bridges Socket.io to NATS subjects.

Architecture

Your Module (browser)

    │  Socket.io (WebSocket)

WebSocket Gateway (wss://ws.insolitum.ai)

    │  NATS protocol

NATS Cluster

    ├── neurosense-core (telemetry)
    ├── fabrica-core (production events)
    ├── nexus-core (AI decisions)
    └── other modules

useNats Hook

The useNats hook manages the WebSocket connection and provides subscribe/publish methods:

import { useNats } from '@/hooks/useNats';
 
export default function LiveDashboard() {
  const { connected, subscribe, publish } = useNats();
 
  useEffect(() => {
    if (!connected) return;
 
    const unsub = subscribe('telemetry', (event) => {
      console.log('Subject:', event.subject);
      console.log('Data:', event.data);
    });
 
    return unsub; // cleanup on unmount
  }, [connected, subscribe]);
 
  return (
    <div>
      <span className={connected ? 'text-green-400' : 'text-red-400'}>
        {connected ? 'Connected' : 'Disconnected'}
      </span>
    </div>
  );
}

Hook API

PropertyTypeDescription
connectedbooleanWhether the WebSocket connection is active
subscribe(channel, callback) => unsubscribeSubscribe to a NATS channel. Returns cleanup function.
publish(subject, data) => voidPublish an event to a NATS subject

Available Channels

ChannelEventsSource
telemetrySensor readings (temperature, humidity, battery)neurosense-core
alertsThreshold alerts (high temp, low battery, device offline)neurosense-core
eventsGeneral application eventsVarious services
modulesModule-to-module custom eventsPartner modules
systemSystem health, service statusInfrastructure

NATS Subjects

Events are organized by subject patterns:

const NATS_SUBJECTS = {
  // All telemetry for a tenant
  telemetry: (tenantId) => `telemetry.${tenantId}.>`,
 
  // Specific device telemetry
  telemetryDevice: (tenantId, deviceId) =>
    `telemetry.${tenantId}.${deviceId}`,
 
  // Alerts
  alerts: (tenantId) => `alerts.${tenantId}.>`,
  alertCreated: (tenantId) => `alerts.${tenantId}.created`,
 
  // Module events
  moduleEvents: (moduleId, tenantId) =>
    `modules.${moduleId}.${tenantId}.>`,
 
  // System
  systemHealth: 'system.health.>',
};

Event Types

Telemetry Reading

interface TelemetryReading {
  device_id: string;
  sensor_id: string;
  tenant_id: string;
  temperature?: number;
  humidity?: number;
  battery?: number;
  rssi?: number;
  timestamp: string;
}

Alert Event

interface AlertEvent {
  id: string;
  tenant_id: string;
  device_id: string;
  type: 'temperature_high' | 'temperature_low' | 'humidity_high'
      | 'humidity_low' | 'battery_low' | 'device_offline' | 'custom';
  severity: 'info' | 'warning' | 'critical';
  message: string;
  value?: number;
  threshold?: number;
  created_at: string;
}

Module Event (Custom)

interface ModuleEvent {
  module_id: string;
  tenant_id: string;
  event_type: string;
  payload: Record<string, unknown>;
  timestamp: string;
}

Publishing Custom Events

Send events that other modules can subscribe to:

const { publish } = useNats();
 
// Publish a custom event
publish('modules.my-analytics.report-generated', {
  module_id: 'my-analytics',
  tenant_id: organizationId,
  event_type: 'report_generated',
  payload: {
    report_id: '123',
    title: 'Monthly Summary',
  },
  timestamp: new Date().toISOString(),
});

Custom events should follow the subject pattern modules.{your_module_id}.{tenant_id}.{event_type} for proper routing and tenant isolation.

Connection Management

The useNats hook automatically:

  • Connects when auth tokens are available
  • Authenticates with the WebSocket gateway using the Supabase access token
  • Reconnects on disconnect (up to 10 attempts with 1s delay)
  • Disconnects on component unmount
  • Scopes subscriptions to the current tenant
const socket = io(WS_URL, {
  auth: {
    token: session.access_token,
    tenantId: organizationId,
  },
  transports: ['websocket'],
  reconnection: true,
  reconnectionDelay: 1000,
  reconnectionAttempts: 10,
});

Environment Variables

# WebSocket gateway URL
NEXT_PUBLIC_WS_URL=ws://localhost:4200    # development
NEXT_PUBLIC_WS_URL=wss://ws.insolitum.ai  # production

On this page