2025-04-13 18:31:40 +00:00

83 lines
2.6 KiB
JavaScript

// jsonrpc.js - Implementation of JSON-RPC 2.0 protocol for Moonraker communication
export class JsonRPC {
constructor() {
this.id_counter = 0;
this.methods = {};
this.pending_requests = {};
}
// Generate a unique ID for RPC requests
generate_id() {
return this.id_counter++;
}
// Register a method to handle incoming notifications/responses
register_method(method_name, callback) {
this.methods[method_name] = callback;
}
// Process incoming messages
process_message(message) {
if (message.method && this.methods[message.method]) {
// Handle method call or notification
this.methods[message.method](message.params);
} else if (message.id !== undefined) {
// Handle response to a previous request
const rpc_promise = this.pending_requests[message.id];
if (rpc_promise) {
if (message.error) {
rpc_promise.reject(message.error);
} else {
rpc_promise.resolve(message.result);
}
delete this.pending_requests[message.id];
}
}
// If it's a notification without a registered method, ignore it
}
// Call a method without parameters
call_method(method) {
return this.call_method_with_kwargs(method, {});
}
// Call a method with parameters
call_method_with_kwargs(method, params) {
const id = this.generate_id();
const request = {
jsonrpc: "2.0",
method: method,
params: params,
id: id,
};
return new Promise((resolve, reject) => {
this.pending_requests[id] = { resolve, reject };
console.log(`Sending JSON-RPC request: ${JSON.stringify(request)}`);
// The actual sending of the message is done by the WebSocket connection
// This just prepares the message and returns a promise
if (this.socket) {
this.socket.send(JSON.stringify(request));
} else {
// If socket is not directly attached to this instance, the caller
// is responsible for sending the serialized request
this.last_request = JSON.stringify(request);
}
});
}
// For external socket handling
get_last_request() {
const req = this.last_request;
this.last_request = null;
return req;
}
// Associate a WebSocket with this RPC instance for direct communication
set_socket(socket) {
this.socket = socket;
}
}