Skip to main content

Overview

Every DeviceClient instance includes a cdn property for uploading files (screenshots, logs, sensor data exports) to the Lua CDN and downloading files from it. The CDN is authenticated using the same API key as the device connection.

Methods

upload

Upload a file to the CDN. Returns a CdnUploadResult with the file ID and public URL.
const result = await device.cdn.upload(data, filename, contentType);
data
Buffer | Blob
required
File content as a Node.js Buffer or Blob.
filename
string
required
Filename including extension (e.g., screenshot.png, sensor-log.csv).
contentType
string
MIME type (e.g., image/png, text/csv). Defaults to application/octet-stream.
Returns: CdnUploadResult
interface CdnUploadResult {
  fileId: string;      // Unique file identifier
  mediaType: string;   // Detected MIME type
  extension: string;   // File extension
  url: string;         // Public URL (https://cdn.heylua.ai/{fileId})
}

download

Download a file from the CDN by its file ID.
const buffer = await device.cdn.download(fileId);
fileId
string
required
The file ID returned from a previous upload.
Returns: Buffer containing the file content.

getUrl

Get the public URL for a file without downloading it.
const url = device.cdn.getUrl(fileId);
// https://cdn.heylua.ai/{fileId}
fileId
string
required
The file ID returned from a previous upload.
Returns: string — the full CDN URL.

Use Cases

Screenshots

Kiosk devices capturing screen state for debugging or audit.

Sensor Logs

Periodic CSV or JSON exports of accumulated sensor readings.

Photos

Camera-equipped devices uploading inspection photos.

Firmware Reports

Diagnostic reports uploaded for agent analysis.

Example: Screenshot Upload

A kiosk device that takes a screenshot when the agent requests it and uploads it to the CDN:
import { DeviceClient } from '@lua-ai/device-client';
import { execSync } from 'child_process';
import fs from 'fs';

const device = new DeviceClient({
  agentId: process.env.LUA_AGENT_ID!,
  apiKey: process.env.LUA_API_KEY!,
  deviceName: 'lobby-kiosk',
  commands: [
    {
      name: 'take_screenshot',
      description: 'Capture a screenshot of the kiosk display and upload it',
    },
    {
      name: 'upload_logs',
      description: 'Upload the last hour of application logs',
    },
  ],
});

device.onCommand('take_screenshot', async () => {
  // Capture screenshot (Linux with scrot, macOS with screencapture)
  const tmpPath = '/tmp/kiosk-screenshot.png';
  execSync(`screencapture -x ${tmpPath}`);

  const screenshot = fs.readFileSync(tmpPath);
  const result = await device.cdn.upload(screenshot, 'kiosk-screenshot.png', 'image/png');

  return {
    message: 'Screenshot captured and uploaded',
    url: result.url,
    fileId: result.fileId,
    size: screenshot.length,
  };
});

device.onCommand('upload_logs', async () => {
  const logPath = '/var/log/kiosk/app.log';
  const logContent = fs.readFileSync(logPath);

  const result = await device.cdn.upload(
    logContent,
    `kiosk-logs-${new Date().toISOString().slice(0, 10)}.log`,
    'text/plain',
  );

  return {
    message: 'Logs uploaded',
    url: result.url,
    fileId: result.fileId,
    lines: logContent.toString().split('\n').length,
  };
});

async function main() {
  await device.connect();
  console.log('Kiosk device online');
}

main().catch(console.error);

Next Steps

Node.js Client

Full client reference including CDN property

Retail Kiosk Example

Complete kiosk example with CDN uploads

API Reference

CDN class method signatures