SocketClient.ts•5.76 kB
import * as net from 'net';
export class RevitClientConnection {
host: string;
port: number;
socket: net.Socket;
isConnected: boolean = false;
responseCallbacks: Map<string, (response: string) => void> = new Map();
buffer: string = '';
constructor(host: string, port: number) {
this.host = host;
this.port = port;
this.socket = new net.Socket();
this.setupSocketListeners();
}
private setupSocketListeners(): void {
this.socket.on('connect', () => {
this.isConnected = true;
console.error('[DEBUG] Connected to Revit socket server');
});
this.socket.on('data', (data) => {
// 将接收到的数据添加到缓冲区
const dataString = data.toString();
console.error(`[DEBUG] Received data: ${dataString.substring(0, 200)}${dataString.length > 200 ? '...' : ''}`);
this.buffer += dataString;
// 尝试解析完整的JSON响应
this.processBuffer();
});
this.socket.on('close', () => {
this.isConnected = false;
console.error('[DEBUG] Socket connection closed');
});
this.socket.on('error', (error) => {
console.error('RevitClientConnection error:', error);
this.isConnected = false;
});
}
private processBuffer(): void {
try {
// 尝试解析JSON
const response = JSON.parse(this.buffer);
// 如果成功解析,处理响应并清空缓冲区
console.error(`[DEBUG] Successfully parsed response: ${JSON.stringify(response).substring(0, 200)}...`);
this.handleResponse(this.buffer);
this.buffer = '';
} catch (e) {
// 如果解析失败,可能是因为数据不完整,继续等待更多数据
console.error(`[DEBUG] Failed to parse buffer (may be incomplete): ${this.buffer.substring(0, 100)}...`);
}
}
public connect(): boolean {
if (this.isConnected) {
console.error('[DEBUG] Already connected to Revit socket server');
return true;
}
try {
console.error(`[DEBUG] Attempting to connect to Revit socket server at ${this.host}:${this.port}`);
this.socket.connect(this.port, this.host);
return true;
} catch (error) {
console.error('Failed to connect:', error);
return false;
}
}
public disconnect(): void {
console.error('[DEBUG] Disconnecting from Revit socket server');
this.socket.end();
this.isConnected = false;
}
private generateRequestId(): string {
return Date.now().toString() + Math.random().toString().substring(2, 8);
}
private handleResponse(responseData: string): void {
try {
const response = JSON.parse(responseData);
// 从响应中获取ID
const requestId = response.id || 'default';
console.error(`[DEBUG] Handling response for request ID: ${requestId}`);
const callback = this.responseCallbacks.get(requestId);
if (callback) {
callback(responseData);
this.responseCallbacks.delete(requestId);
console.error(`[DEBUG] Callback executed and removed for request ID: ${requestId}`);
} else {
console.error(`[DEBUG] No callback found for request ID: ${requestId}`);
}
} catch (error) {
console.error('Error parsing response:', error);
}
}
public sendCommand(command: string, params: any = {}): Promise<any> {
return new Promise((resolve, reject) => {
try {
if (!this.isConnected) {
console.error('[DEBUG] Not connected, attempting to connect before sending command');
this.connect();
}
// 生成请求ID
const requestId = this.generateRequestId();
console.error(`[DEBUG] Generated request ID: ${requestId} for command: ${command}`);
// 创建符合JSON-RPC标准的请求对象
const commandObj = {
jsonrpc: '2.0',
method: command,
params: params,
id: requestId,
};
// 存储回调函数
this.responseCallbacks.set(requestId, (responseData) => {
try {
const response = JSON.parse(responseData);
console.error(`[DEBUG] Received response for request ID: ${requestId}`);
if (response.error) {
console.error(`[DEBUG] Error in response: ${JSON.stringify(response.error)}`);
reject(new Error(response.error.message || 'Unknown error from Revit'));
} else {
console.error(`[DEBUG] Success response received with result type: ${typeof response.result}`);
resolve(response.result);
}
} catch (error) {
console.error(`[DEBUG] Error parsing response data: ${responseData.substring(0, 100)}...`);
if (error instanceof Error) {
reject(new Error(`Failed to parse response: ${error.message}`));
} else {
reject(new Error(`Failed to parse response: ${String(error)}`));
}
}
});
// 发送命令
const commandString = JSON.stringify(commandObj);
console.error(`[DEBUG] Sending command: ${commandString.substring(0, 200)}${commandString.length > 200 ? '...' : ''}`);
this.socket.write(commandString);
// 设置超时
setTimeout(() => {
if (this.responseCallbacks.has(requestId)) {
console.error(`[DEBUG] Command timed out after 2 minutes: ${command} (request ID: ${requestId})`);
this.responseCallbacks.delete(requestId);
reject(new Error(`Command timed out after 2 minutes: ${command}`));
}
}, 120000); // 2分钟超时
} catch (error) {
console.error(`[DEBUG] Error in sendCommand: ${error}`);
reject(error);
}
});
}
}