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 );
File content as a Node.js Buffer or Blob.
Filename including extension (e.g., screenshot.png, sensor-log.csv).
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 );
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}
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