Skip to main content

Remote Procedure Call (RPC)

Receive RPC calls from the App SDK and return a response. Your app sends a request, your device processes it and replies.

Overview

RPC uses a request/reply pattern — your app sends a request, your device processes it and sends a response. Unlike commands, the caller waits for a response.

Access via device.rpc.

API

listen()

Register a handler for incoming RPC calls matching a given name.

await device.rpc.listen(name, callback)
ParameterTypeDescription
namestringThe RPC name to listen for
callbackfunctionCalled when an RPC request arrives. Receives an RpcRequest object

Throws DuplicateListenerError if a listener with the same name is already registered

Throws ValidationError if name contains invalid characters

Naming rules

Names can only contain letters, numbers, hyphens, and underscores (A-Z, a-z, 0-9, -, _). This applies to RPC names, command names, and event names.

off()

Unregister a previously registered RPC listener.

await device.rpc.off(name)
ParameterTypeDescription
namestringThe RPC name to stop listening for

Returns true if the listener was removed, false if no listener existed for that name

The RpcRequest Object

When an RPC call arrives, your callback receives an RpcRequest object with:

Property/MethodDescription
request.payloadThe data sent by the caller
request.respond(data)Send a success response back
request.error(data)Send an error response back

Every RPC handler should call either respond() or error() — the caller is waiting for a reply.

Listen for RPC Calls

await device.rpc.listen("get_status", (request) => {
const status = {
uptime: process.uptime(),
temperature: readSensor(),
firmware: "1.2.0",
};

request.respond(status);
});

Responding with an Error

If the request can't be fulfilled, use request.error() instead of request.respond().

await device.rpc.listen("restart_service", (request) => {
const { service } = request.payload;

if (!isValidService(service)) {
request.error({ message: `Unknown service: ${service}` });
return;
}

restartService(service);
request.respond({ restarted: service });
});

Remove a Listener

await device.rpc.off("get_status");

Safe to call even if no listener exists for that name.

Error Handling

// registering the same name twice throws DuplicateListenerError
await device.rpc.listen("get_status", handler);

try {
await device.rpc.listen("get_status", anotherHandler);
} catch (err) {
// DuplicateListenerError: "get_status" is already registered
console.error(err.message);
}

To replace a listener, call off() first, then listen() again with the new handler.