/** * Edge 代理模式扩展 * Edge 作为设备的代理,管理本地设备并与 Gateway 通信 */ import { BaseMessage, MessageType, ClientType, CommandMessage, CommandResponseMessage, RegisterMessage, MessageFactory, Priority } from './index'; // Edge 管理的设备信息 export interface ManagedDevice { deviceId: string; deviceType: string; status: 'online' | 'offline' | 'error'; lastSeen: string; capabilities?: string[]; metadata?: Record; } // Edge 注册消息(包含管理的设备列表) export interface EdgeRegisterMessage extends RegisterMessage { managedDevices?: ManagedDevice[]; } // Edge 状态报告 export interface EdgeStatusReport { edgeId: string; status: 'healthy' | 'degraded' | 'error'; managedDevices: ManagedDevice[]; statistics: { totalDevices: number; onlineDevices: number; commandsProcessed: number; errors: number; uptime: number; }; timestamp: string; } // 设备状态变更通知 export interface DeviceStatusChangeMessage extends BaseMessage { type: 'device_status_change'; edgeId: string; deviceId: string; previousStatus: string; currentStatus: string; reason?: string; } // Edge 批量设备命令 export interface EdgeBatchCommandMessage extends CommandMessage { targetDevices: string[]; // Edge 管理的设备ID列表 failureStrategy?: 'stop_on_first_failure' | 'continue_on_failure'; } // Edge 命令路由信息 export interface EdgeCommandRoute { deviceId: string; edgeId: string; lastUpdated: string; } /** * Edge 代理工具类 */ export class EdgeProxyUtils { /** * 创建 Edge 注册消息(包含管理的设备) */ static createEdgeRegisterMessage( edgeId: string, managedDevices: ManagedDevice[], capabilities?: string[] ): EdgeRegisterMessage { return { type: MessageType.REGISTER, clientId: edgeId, clientType: ClientType.EDGE, clientInfo: { version: '1.0.0', platform: 'edge-proxy', capabilities: [ 'device_proxy', 'batch_command', 'status_report', ...(capabilities || []) ] }, managedDevices, timestamp: new Date().toISOString(), version: '2.0' }; } /** * 创建设备状态变更通知 */ static createDeviceStatusChange( edgeId: string, deviceId: string, previousStatus: string, currentStatus: string, reason?: string ): DeviceStatusChangeMessage { return { type: 'device_status_change', edgeId, deviceId, previousStatus, currentStatus, reason, timestamp: new Date().toISOString() }; } /** * 创建 Edge 状态报告 */ static createEdgeStatusReport( edgeId: string, managedDevices: ManagedDevice[], statistics: EdgeStatusReport['statistics'] ): EdgeStatusReport { return { edgeId, status: this.calculateEdgeHealth(managedDevices, statistics), managedDevices, statistics, timestamp: new Date().toISOString() }; } /** * 创建批量设备命令 */ static createEdgeBatchCommand( requestRef: string, edgeId: string, targetDevices: string[], command: CommandMessage['command'], options?: { priority?: Priority; timeout?: number; failureStrategy?: EdgeBatchCommandMessage['failureStrategy']; } ): EdgeBatchCommandMessage { return { type: MessageType.COMMAND, requestRef, clientId: edgeId, command, targetDevices, priority: options?.priority || Priority.NORMAL, timeout: options?.timeout || (10000 * targetDevices.length), failureStrategy: options?.failureStrategy || 'continue_on_failure', timestamp: new Date().toISOString(), version: '2.0' }; } /** * 解析设备 ID 获取 Edge 路由 * 假设设备 ID 格式: edge001:device001 */ static parseDeviceRoute(deviceId: string): EdgeCommandRoute | null { const parts = deviceId.split(':'); if (parts.length !== 2) return null; return { edgeId: parts[0], deviceId: parts[1], lastUpdated: new Date().toISOString() }; } /** * 构建完整的设备 ID */ static buildFullDeviceId(edgeId: string, localDeviceId: string): string { return `${edgeId}:${localDeviceId}`; } /** * 转换 Backend 命令为 Edge 本地命令 */ static convertToLocalCommand( command: CommandMessage, targetDeviceId: string ): CommandMessage { const route = this.parseDeviceRoute(command.clientId); if (!route) return command; return { ...command, clientId: targetDeviceId, metadata: { ...command.metadata, originalSiteId: command.clientId, routedThrough: route.edgeId } }; } /** * 聚合多个设备响应 */ static aggregateDeviceResponses( originalRequestRef: string, deviceResponses: Array<{ deviceId: string; response: CommandResponseMessage; }> ): CommandResponseMessage { const allSuccess = deviceResponses.every(r => r.response.status === 'completed'); const results = deviceResponses.map(r => ({ deviceId: r.deviceId, status: r.response.status, result: r.response.result, error: r.response.error })); return { type: MessageType.COMMAND_RESPONSE, requestRef: originalRequestRef, status: allSuccess ? 'completed' : 'failed', result: { success: allSuccess, data: { deviceCount: deviceResponses.length, results } }, timestamp: new Date().toISOString() }; } /** * 计算 Edge 健康状态 */ private static calculateEdgeHealth( devices: ManagedDevice[], statistics: EdgeStatusReport['statistics'] ): EdgeStatusReport['status'] { const onlineRatio = statistics.onlineDevices / statistics.totalDevices; const errorRate = statistics.errors / (statistics.commandsProcessed || 1); if (onlineRatio < 0.5 || errorRate > 0.1) { return 'error'; } else if (onlineRatio < 0.8 || errorRate > 0.05) { return 'degraded'; } return 'healthy'; } } /** * Edge 代理实现示例 */ export class EdgeProxy { private edgeId: string; private devices = new Map(); private gateway: any; // WebSocket connection private statistics = { commandsProcessed: 0, errors: 0, startTime: Date.now() }; constructor(edgeId: string) { this.edgeId = edgeId; } /** * 添加本地设备 */ addDevice(device: ManagedDevice) { this.devices.set(device.deviceId, device); // 通知 Gateway 设备状态变更 if (this.gateway) { const notification = EdgeProxyUtils.createDeviceStatusChange( this.edgeId, device.deviceId, 'offline', device.status ); this.gateway.send(JSON.stringify(notification)); } } /** * 注册到 Gateway */ registerToGateway() { const managedDevices = Array.from(this.devices.values()); const registerMsg = EdgeProxyUtils.createEdgeRegisterMessage( this.edgeId, managedDevices, ['local_storage', 'offline_mode'] ); this.gateway.send(JSON.stringify(registerMsg)); } /** * 处理来自 Gateway 的命令 */ async handleGatewayCommand(message: CommandMessage) { // 检查是否是批量命令 const batchCmd = message as EdgeBatchCommandMessage; if (batchCmd.targetDevices) { await this.handleBatchCommand(batchCmd); return; } // 解析目标设备 const route = EdgeProxyUtils.parseDeviceRoute(message.clientId); if (!route || route.edgeId !== this.edgeId) { this.sendErrorResponse(message.requestRef, 'Invalid device route'); return; } // 检查设备是否在线 const device = this.devices.get(route.deviceId); if (!device || device.status !== 'online') { this.sendErrorResponse( message.requestRef, `Device ${route.deviceId} is ${device?.status || 'not found'}` ); return; } try { // 转换为本地命令并执行 const localCommand = EdgeProxyUtils.convertToLocalCommand(message, route.deviceId); const result = await this.executeDeviceCommand(route.deviceId, localCommand); // 发送响应 const response: CommandResponseMessage = { type: MessageType.COMMAND_RESPONSE, requestRef: message.requestRef, status: 'completed', result, timestamp: new Date().toISOString() }; this.gateway.send(JSON.stringify(response)); this.statistics.commandsProcessed++; } catch (error) { this.sendErrorResponse(message.requestRef, error.message); this.statistics.errors++; } } /** * 处理批量命令 */ private async handleBatchCommand(command: EdgeBatchCommandMessage) { const responses: Array<{ deviceId: string; response: CommandResponseMessage }> = []; for (const deviceId of command.targetDevices) { const device = this.devices.get(deviceId); if (!device || device.status !== 'online') { responses.push({ deviceId, response: { type: MessageType.COMMAND_RESPONSE, requestRef: `${command.requestRef}-${deviceId}`, status: 'failed', error: `Device ${deviceId} is ${device?.status || 'not found'}`, timestamp: new Date().toISOString() } }); if (command.failureStrategy === 'stop_on_first_failure') { break; } continue; } try { const localCommand = { ...command, clientId: deviceId }; const result = await this.executeDeviceCommand(deviceId, localCommand); responses.push({ deviceId, response: { type: MessageType.COMMAND_RESPONSE, requestRef: `${command.requestRef}-${deviceId}`, status: 'completed', result, timestamp: new Date().toISOString() } }); } catch (error) { responses.push({ deviceId, response: { type: MessageType.COMMAND_RESPONSE, requestRef: `${command.requestRef}-${deviceId}`, status: 'failed', error: error.message, timestamp: new Date().toISOString() } }); if (command.failureStrategy === 'stop_on_first_failure') { break; } } } // 聚合响应 const aggregatedResponse = EdgeProxyUtils.aggregateDeviceResponses( command.requestRef, responses ); this.gateway.send(JSON.stringify(aggregatedResponse)); } /** * 执行设备命令(模拟) */ private async executeDeviceCommand(deviceId: string, command: any): Promise { // 实际实现中,这里会与物理设备通信 console.log(`Executing command on device ${deviceId}:`, command); // 模拟命令执行 await new Promise(resolve => setTimeout(resolve, 100)); return { success: true, data: { deviceId, commandCode: command.command.commandCode, executedAt: new Date().toISOString() } }; } /** * 发送错误响应 */ private sendErrorResponse(requestRef: string, errorMessage: string) { const response: CommandResponseMessage = { type: MessageType.COMMAND_RESPONSE, requestRef, status: 'failed', error: { code: 'EDGE_ERROR', message: errorMessage, retryable: false }, timestamp: new Date().toISOString() }; this.gateway.send(JSON.stringify(response)); } /** * 定期发送状态报告 */ sendStatusReport() { const report = EdgeProxyUtils.createEdgeStatusReport( this.edgeId, Array.from(this.devices.values()), { totalDevices: this.devices.size, onlineDevices: Array.from(this.devices.values()).filter(d => d.status === 'online').length, commandsProcessed: this.statistics.commandsProcessed, errors: this.statistics.errors, uptime: Date.now() - this.statistics.startTime } ); this.gateway.send(JSON.stringify({ type: 'edge_status_report', ...report })); } }