Command
Receive commands from the App SDK asynchronously. Unlike RPC, commands are fire-and-forget — your device does not send a response back to the caller.
Overview
Commands use durable delivery — if your device is offline when a command is sent, it will be delivered when the device reconnects. If your handler throws an error, the command is automatically retried after a 5-second delay.
Access via device.command.
RPC vs Command
| RPC | Command | |
|---|---|---|
| Direction | App SDK → Device → App SDK | App SDK → Device |
| Response | Device sends a response | No response |
| Delivery | Requires active connection | Durable — delivered even if device is offline |
| Retry | No retry | Auto-retry on handler failure (5s delay) |
API
listen()
Register a handler for incoming commands matching a given name.
- JavaScript
- Python
await device.command.listen(name, callback)await device.command.listen(name, callback)| Parameter | Type | Description |
|---|---|---|
name | string | The command name to listen for |
callback | function | Called when a command arrives. Receives the command payload |
Throws DuplicateListenerError if a listener with the same name is already registered
Throws ValidationError if name contains invalid characters
Names can only contain letters, numbers, hyphens, and underscores (A-Z, a-z, 0-9, -, _).
off()
Unregister a previously registered command listener.
- JavaScript
- Python
await device.command.off(name)await device.command.off(name)| Parameter | Type | Description |
|---|---|---|
name | string | The command name to stop listening for |
Returns true if the listener was removed, false if no listener existed for that name
Listen for Commands
- JavaScript
- Python
await device.command.listen("reboot", (payload) => {
console.log("Reboot requested:", payload);
initiateReboot();
});
await device.command.listen("update_firmware", (payload) => {
const { version, url } = payload;
console.log(`Updating to ${version} from ${url}`);
downloadAndInstall(url);
});
async def handle_reboot(payload):
print("Reboot requested:", payload)
initiate_reboot()
async def handle_update(payload):
version = payload["version"]
url = payload["url"]
print(f"Updating to {version} from {url}")
download_and_install(url)
await device.command.listen("reboot", handle_reboot)
await device.command.listen("update_firmware", handle_update)
Guaranteed Delivery
Commands are durably stored and delivered even if your device is offline when the command is sent. Once your device reconnects, any pending commands are delivered in order.
If your handler throws an error, the command is automatically retried after a 5-second delay, up to a maximum of 5 attempts. If the handler succeeds (no error thrown), the command is acknowledged and won't be delivered again.
- JavaScript
- Python
await device.command.listen("deploy", (payload) => {
const success = deployConfig(payload);
if (!success) {
// throwing an error triggers a retry in 5 seconds
throw new Error("Deploy failed — will retry");
}
});
async def handle_deploy(payload):
success = deploy_config(payload)
if not success:
# raising an error triggers a retry in 5 seconds
raise Exception("Deploy failed — will retry")
await device.command.listen("deploy", handle_deploy)
Remove a Listener
- JavaScript
- Python
await device.command.off("reboot");
await device.command.off("reboot")
Safe to call even if no listener exists for that name.