/** * Backend 升级示例 - 使用新协议与Gateway通信 */ import WebSocket from 'ws'; import { MessageFactory, MessageValidator, ClientType, Priority, isRegisterMessage, isCommandResponseMessage, RegisterAckMessage, CommandResponseMessage } from '@jrsoft/subway-protocol'; export class UpgradedGatewayClient { private ws: WebSocket | null = null; private clientId: string; private sessionId?: string; private reconnectAttempts = 0; private readonly maxReconnectAttempts = 10; constructor( private gatewayUrl: string, clientId?: string ) { this.clientId = clientId || 'backend-server'; } /** * 连接到Gateway */ async connect(): Promise { return new Promise((resolve, reject) => { try { this.ws = new WebSocket(this.gatewayUrl); this.ws.on('open', () => { console.log('Connected to Gateway'); this.reconnectAttempts = 0; this.register(); resolve(); }); this.ws.on('message', (data) => { this.handleMessage(data.toString()); }); this.ws.on('close', () => { console.log('Disconnected from Gateway'); this.sessionId = undefined; this.attemptReconnect(); }); this.ws.on('error', (error) => { console.error('WebSocket error:', error); reject(error); }); } catch (error) { reject(error); } }); } /** * 注册到Gateway - 使用完整的新协议格式 */ private register() { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { console.error('Cannot register: WebSocket not connected'); return; } // 使用新协议创建注册消息 const registerMsg = MessageFactory.createRegisterMessage( this.clientId, ClientType.BACKEND, { version: '1.0.0', platform: 'nodejs', capabilities: ['command', 'program', 'callback'] } ); console.log('Sending registration:', registerMsg); this.ws.send(JSON.stringify(registerMsg)); } /** * 处理来自Gateway的消息 */ private handleMessage(data: string) { try { const message = JSON.parse(data); // 验证消息格式 if (!MessageValidator.validateMessage(message)) { console.error('Invalid message format:', message); return; } switch (message.type) { case 'register_ack': this.handleRegisterAck(message as RegisterAckMessage); break; case 'command_response': if (isCommandResponseMessage(message)) { this.handleCommandResponse(message); } break; default: console.log('Received message:', message.type); } } catch (error) { console.error('Error handling message:', error); } } /** * 处理注册确认 */ private handleRegisterAck(message: RegisterAckMessage) { if (message.success) { console.log('Registration successful'); // 保存sessionId(如果Gateway支持) if (message.sessionId) { this.sessionId = message.sessionId; console.log('Session ID:', this.sessionId); } } else { console.error('Registration failed:', message.error); } } /** * 处理命令响应 */ private handleCommandResponse(message: CommandResponseMessage) { console.log('Command response received:', { requestRef: message.requestRef, status: message.status, executionTime: message.executionTime }); // 处理响应... } /** * 发送命令到设备 */ async sendCommand( deviceSiteId: string, commandCode: string, parameters: any, options?: { priority?: Priority; timeout?: number; callback?: string; } ): Promise { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { throw new Error('WebSocket not connected'); } const command = MessageFactory.createCommandMessage( this.generateRequestRef(), deviceSiteId, { commandCode, deviceType: 'controller', operationType: 'write', parameters }, { priority: options?.priority || Priority.NORMAL, timeout: options?.timeout || 10000, callback: options?.callback } ); console.log('Sending command:', command); this.ws.send(JSON.stringify(command)); } /** * 发送心跳 */ sendHeartbeat() { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { return; } const heartbeat = MessageFactory.createHeartbeatMessage( this.clientId, Date.now() ); this.ws.send(JSON.stringify(heartbeat)); } /** * 尝试重连 */ private attemptReconnect() { if (this.reconnectAttempts >= this.maxReconnectAttempts) { console.error('Max reconnection attempts reached'); return; } this.reconnectAttempts++; const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000); console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`); setTimeout(() => { this.connect().catch(error => { console.error('Reconnection failed:', error); }); }, delay); } /** * 生成请求引用 */ private generateRequestRef(): string { return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } /** * 断开连接 */ disconnect() { if (this.ws) { this.ws.close(); this.ws = null; } } } // 使用示例 async function example() { const client = new UpgradedGatewayClient( 'ws://localhost:3001', 'backend-server' ); try { // 连接到Gateway await client.connect(); // 发送命令 await client.sendCommand( 'device001', 'WRITE_REGISTER', { register: 'R001', value: 100 }, { priority: Priority.HIGH, timeout: 5000, callback: 'http://localhost:18082/api/callback' } ); // 定期发送心跳 setInterval(() => { client.sendHeartbeat(); }, 30000); } catch (error) { console.error('Error:', error); } } export default UpgradedGatewayClient;