---
title: "IoT SDK"
description: "IoT device telemetry and command dispatch with acknowledgment tracking for connected device fleets."
---

# @nolag/iot

IoT device telemetry and command dispatch with acknowledgment tracking.

## Overview

Connect IoT devices and controllers over real-time channels. Devices push telemetry (sensor readings, status updates, or any structured measurement) while controllers dispatch commands with Promise-based acknowledgment tracking and configurable timeouts. Two roles participate in a device group: **devices** report data and acknowledge commands, and **controllers** monitor telemetry streams and issue commands. A single client can act as both. Groups organise devices by fleet, physical location, or function.

### Key Features

- Real-time telemetry broadcast from devices to all group subscribers
- Promise-based command dispatch with configurable acknowledgment timeout
- Ephemeral telemetry for high-frequency data without storage overhead
- Ephemeral commands with fire-and-forget dispatch and ack tracking
- Ephemeral acknowledgment channel for command response tracking
- Device online/offline presence via lobby
- Multiple groups per connection; join by zone, building floor, vehicle type, etc.

## How It Works

`NoLagIoT` wraps the `@nolag/js-sdk` client and manages a lobby that reflects device presence. Calling `joinGroup(name)` returns a `DeviceGroup` that subscribes to three topics: `telemetry` for ephemeral sensor readings, `commands` for ephemeral command payloads, and `_cmd_ack` for ephemeral acknowledgment messages. All topics are ephemeral (no server-side retention) to handle high-frequency telemetry without storage overhead. When a controller calls `sendCommand()` the SDK stores a pending Promise keyed on the command ID; when the target device calls `ackCommand()` the matching Promise resolves or rejects based on the reported status.

| Topic | Purpose | Replay |
| --- | --- | --- |
| `telemetry` | Sensor readings and device status updates | Ephemeral |
| `commands` | Commands dispatched to devices | Ephemeral |
| `_cmd_ack` | Command acknowledgment messages | Ephemeral |

## Installation

```bash [Terminal]
npm install @nolag/iot @nolag/js-sdk
```

## Quick Start

```typescript [TypeScript]
import { NoLagIoT } from '@nolag/iot'

const client = new NoLagIoT('your-access-token')
await client.connect()

// Join a device group (organised by fleet, location, or function)
const group = await client.joinGroup('sensors-floor-3')

// ── Device side ───────────────────────────────────────────────────────────────

// Send a telemetry reading
group.sendTelemetry('temperature', 22.4, {
  unit: 'celsius',
  sensorId: 'tmp_01',
})

group.sendTelemetry('humidity', 61, { unit: 'percent' })

// Listen for commands sent by controllers
group.on('command', async ({ command }) => {
  console.log('Received command:', command.name, command.params)

  // Execute the command...
  const result = await handleCommand(command)

  // Acknowledge success
  await group.ackCommand(command.commandId, 'success', result)
})

// ── Controller side ───────────────────────────────────────────────────────────

// Watch all telemetry from the group
group.on('telemetry', ({ deviceId, sensorId, value, opts, timestamp }) => {
  console.log(`[${deviceId}] ${sensorId}: ${value}`)
})

// Retrieve the last known reading for a specific sensor
const reading = await group.getTelemetry('device-007', 'temperature')
console.log('Last temperature:', reading)

// Send a command (returns a Promise that resolves when the device acks)
try {
  const cmd = await group.sendCommand('device-007', 'reboot', {
    delay: 5000,
  })
  // Promise resolves once the device calls ackCommand
  console.log('Command acked by device:', cmd.status)
} catch (err) {
  // Throws if the device does not ack within the configured timeout
  console.error('Command timed out or rejected:', err)
}

// Monitor ack events
group.on('commandAck', ({ commandId, deviceId, status, result }) => {
  console.log(`Command ${commandId} acked by ${deviceId} with status ${status}`)
})

// Presence
client.on('deviceOnline', ({ deviceId }) => console.log('Online:', deviceId))
client.on('deviceOffline', ({ deviceId }) => console.log('Offline:', deviceId))
```

## API Reference

### NoLagIoT

| Method | Returns | Description |
| --- | --- | --- |
| `connect()` | `Promise<void>` | Establish the WebSocket connection and join the lobby. |
| `disconnect()` | `void` | Close the connection and leave the lobby. |
| `joinGroup(name)` | `Promise<DeviceGroup>` | Subscribe to a device group. Returns the group instance. |
| `leaveGroup(name)` | `Promise<void>` | Unsubscribe from a device group and release its resources. |
| `getOnlineDevices()` | `Device[]` | Return all devices currently present in the lobby. |

### NoLagIoT Events

| Event | Payload | Description |
| --- | --- | --- |
| `connected` | none | WebSocket connection established. |
| `disconnected` | `reason: string` | Connection closed. |
| `reconnected` | none | Connection restored; room membership and presence are restored automatically. |
| `error` | `error: Error` | A transport or protocol error occurred. |
| `deviceOnline` | `device: Device` | A device joined the lobby. |
| `deviceOffline` | `device: Device` | A device left the lobby. |

### DeviceGroup

| Method | Role | Returns | Description |
| --- | --- | --- | --- |
| `sendTelemetry(sensorId, value, opts?)` | Device | `void` | Publish a sensor reading to the group. `opts` carries metadata such as unit or tags. |
| `getTelemetry(deviceId?, sensorId?)` | Both | `Promise<TelemetryReading[]>` | Fetch the most recent telemetry. Omit arguments to get all devices and sensors. |
| `sendCommand(targetDeviceId, command, params?)` | Controller | `Promise<DeviceCommand>` | Dispatch a named command to a device. Resolves when the device acknowledges, or rejects on timeout. |
| `ackCommand(commandId, status, result?)` | Device | `void` | Send an acknowledgment for a received command. `status` is `'success'` or `'error'`. |

### DeviceGroup Events

| Event | Payload | Description |
| --- | --- | --- |
| `telemetry` | `{ deviceId, sensorId, value, opts?, timestamp }` | A telemetry reading was received from a device in the group. |
| `command` | `{ command: DeviceCommand }` | A command was dispatched to this device (device role only). |
| `commandAck` | `{ commandId, deviceId, status, result? }` | A device acknowledged a previously dispatched command. |
| `deviceJoined` | `device: Device` | A device joined this group. |
| `deviceLeft` | `device: Device` | A device left this group. |
