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
npm install @nolag/iot @nolag/js-sdk
Quick Start
import { NoLagIoT } from'@nolag/iot'const client = newNoLagIoT('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 = awaithandleCommand(command)
// Acknowledge successawait 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 sensorconst 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.