Skip to content

Node.js SDK

The Node.js SDK is for TypeScript or JavaScript device programs. The package uses @device-agent/device-sdk and BaseDevice to handle MQTT connection, command subscription, command responses, state reports, and event reports. Add real device behavior in src/device.ts.

Use Cases

  • TypeScript/JavaScript is used for device-side, gateway, or edge services.
  • The device needs an existing Node.js service, HTTP API, database, or business system.
  • Claude Code, Cursor, or Codex will continue the device-side implementation.

Package Contents

FilePurpose
src/index.tsStartup entry point that loads .env and creates the device instance
src/device.tsDevice logic entry point that extends BaseDevice
device-spec.jsonCurrent DeviceSpec, used for command validation and state fields
packages/device-sdkLocal copy of the device-side SDK with BaseDevice, voice, and vision clients
AGENTS.md / CLAUDE.mdContext for local AI coding tools

For a real device, you mainly work in src/device.ts: handle commands, call hardware or business services, update state, and report events.

Access Steps

  1. Download the Node.js SDK package.
  2. Copy .env.example to .env and update MQTT broker or credentials if needed.
  3. Install dependencies and start the program.
  4. Replace the default behavior in src/device.ts with real device logic.
  5. Return to the Device Agent workspace, confirm the device is online, and test a control command.
bash
cp .env.example .env
npm install
npm run start

Implement Device Logic

The device class in src/device.ts extends BaseDevice. After connection, it publishes a state snapshot. Commands enter handleCommand(). Call hardware interfaces or business services here:

ts
protected override async handleCommand(command: DeviceCommandMessage) {
  if (command.cmd === "set_temperature") {
    const target = Number(command.params?.target_temperature);

    await thermostatClient.setTargetTemperature(target);
    this.patchState({ target_temperature: target });
    await this.publishStateSnapshot();

    return { code: 0, msg: "ok", data: { target_temperature: target } };
  }

  return { code: 404, msg: `Unknown command: ${command.cmd}` };
}

BaseDevice handles MQTT connection, command subscription, response publishing, and state reporting. Keep command names, parameter names, and state fields aligned with device-spec.json.

After state changes, call publishStateSnapshot(). To report an event, use an event already defined in the DeviceSpec:

ts
await this.sendEvent("temperature_alarm", {
  current_temperature: 32.5,
  level: "warning",
});

Voice Access Code

VoiceClient in the Node.js SDK is for device-side voice conversations. The device connects to /ws/voice, sends 16 kHz mono Int16LE PCM audio, and listens for ASR text, agent replies, and TTS audio events.

ts
import { VoiceClient } from "@device-agent/device-sdk";

const voice = new VoiceClient({
  wsUrl: "ws://127.0.0.1:3001/ws/voice",
  deviceId: "device-001",
  productId: "agent-001",
});

voice.on("agentReply", (text) => console.log(text));

await voice.connect();
voice.startListening("manual");
voice.sendAudio(pcmChunk);
voice.stopListening();

packages/device-sdk/examples/voice-chat.ts is the complete example. For a real device, connect microphone capture and speaker playback to sendAudio() and TTS events.

Vision Recognition Code

The Node.js toolkit derives /api/vision/frames and /api/chat from VOICE_CHAT_HOST. When the DeviceSpec contains one of these commands, src/device.ts runs the photo recognition flow:

  • capture_and_recognize
  • take_photo_vision
  • vision_recognize
  • photo_identify

The default flow checks imageDataUrl and imageBase64 in command parameters, then VISION_FALLBACK_IMAGE_DATA_URL in .env. For a real device, override captureLocalVisionImage() to read one image from a camera, screenshot, or image file.

ts
protected override async captureLocalVisionImage() {
  return {
    mimeType: "image/jpeg",
    imageBase64: await readCameraFrameAsBase64(),
    source: "sdk-camera",
  };
}

The device uploads the image, calls /api/chat with visionRefs, and returns the recognition result as the command response. This is command-triggered single-frame recognition, not continuous video streaming.

Continue with a Local AI Coding Tool

Node.js packages include AGENTS.md, CLAUDE.md, and device implementation guidance. Open the package folder in Claude Code, Cursor, or Codex and ask it to continue src/device.ts based on device-spec.json.

Verify Access

After the program starts, return to the Device Agent workspace and confirm:

  1. The device appears in the device list and is online.
  2. Current state shows fields reported by the Node.js program.
  3. A conversation command executes the logic in handleCommand().
  4. If sendEvent() is called, the event appears in recent events.