// 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; } }