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.
- JavaScript
- Python
await device.rpc.listen(name, callback)await device.rpc.listen(name, callback)| Parameter | Type | Description |
|---|---|---|
name | string | The RPC name to listen for |
callback | function | Called 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
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.
- JavaScript
- Python
await device.rpc.off(name)await device.rpc.off(name)| Parameter | Type | Description |
|---|---|---|
name | string | The 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/Method | Description |
|---|---|
request.payload | The 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
- JavaScript
- Python
await device.rpc.listen("get_status", (request) => {
const status = {
uptime: process.uptime(),
temperature: readSensor(),
firmware: "1.2.0",
};
request.respond(status);
});
async def handle_get_status(request):
status = {
"uptime": get_uptime(),
"temperature": read_sensor(),
"firmware": "1.2.0",
}
request.respond(status)
await device.rpc.listen("get_status", handle_get_status)
Responding with an Error
If the request can't be fulfilled, use request.error() instead of request.respond().
- JavaScript
- Python
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 });
});
async def handle_restart(request):
service = request.payload.get("service")
if not is_valid_service(service):
request.error({"message": f"Unknown service: {service}"})
return
restart_service(service)
request.respond({"restarted": service})
await device.rpc.listen("restart_service", handle_restart)
Remove a Listener
- JavaScript
- Python
await device.rpc.off("get_status");
await device.rpc.off("get_status")
Safe to call even if no listener exists for that name.
Error Handling
- JavaScript
- Python
// 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);
}
await device.rpc.listen("get_status", handler)
try:
await device.rpc.listen("get_status", another_handler)
except DuplicateListenerError as err:
# "get_status" is already registered
print(err)
To replace a listener, call off() first, then listen() again with the new handler.