# Progress Update 示例

本文档展示如何使用 progress_update 消息进行进度报告。

## 基本概念

Progress Update 用于长时间运行操作的实时进度反馈，适用于：
- Complex 命令执行
- Batch 命令批量处理
- Program 程序上传
- 任何需要进度反馈的操作

## Complex 命令进度更新

### 健康检查示例

```typescript
// 设备端实现
class HealthCheckHandler {
  async executeHealthCheck(command: CommandMessage, gateway: GatewayConnection) {
    const requestRef = command.requestRef;
    const totalSteps = 4;
    let currentStep = 0;
    
    try {
      // Step 1: 检查开关状态
      currentStep++;
      const switchStatus = await this.checkSwitchStatus();
      
      await gateway.sendProgressUpdate({
        type: MessageType.PROGRESS_UPDATE,
        requestRef,
        status: ProgressStatus.IN_PROGRESS,
        phase: 'checking_switch',
        progress: (currentStep / totalSteps) * 100,
        sourceType: 'COMMAND',
        command: {
          commandType: CommandType.SIMPLE,
          commandCode: 'READ_SWITCH_STATUS',
          deviceType: 'controller',
          deviceId: this.deviceId,
          operationType: OperationType.READ,
          result: switchStatus
        },
        report: {
          level: ReportLevel.INFO,
          message: '开关状态检查完成',
          data: { switchCount: switchStatus.count }
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
      // Step 2: 读取配置
      currentStep++;
      const config = await this.readConfiguration();
      
      await gateway.sendProgressUpdate({
        type: MessageType.PROGRESS_UPDATE,
        requestRef,
        status: ProgressStatus.IN_PROGRESS,
        phase: 'reading_config',
        progress: (currentStep / totalSteps) * 100,
        sourceType: 'COMMAND',
        command: {
          commandType: CommandType.SIMPLE,
          commandCode: 'READ_CONFIG',
          deviceType: 'controller',
          deviceId: this.deviceId,
          operationType: OperationType.READ,
          result: config
        },
        report: {
          level: ReportLevel.INFO,
          message: '配置读取完成'
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
      // Step 3: 检查同步器
      currentStep++;
      const syncStatus = await this.checkSynchronizer();
      
      await gateway.sendProgressUpdate({
        type: MessageType.PROGRESS_UPDATE,
        requestRef,
        status: ProgressStatus.IN_PROGRESS,
        phase: 'checking_synchronizer',
        progress: (currentStep / totalSteps) * 100,
        sourceType: 'COMMAND',
        command: {
          commandType: CommandType.SIMPLE,
          commandCode: 'CHECK_SYNC',
          deviceType: 'synchronizer',
          deviceId: 1,
          operationType: OperationType.READ,
          result: syncStatus
        },
        report: {
          level: syncStatus.healthy ? ReportLevel.INFO : ReportLevel.WARNING,
          message: syncStatus.healthy ? '同步器状态正常' : '同步器存在问题',
          code: syncStatus.healthy ? 'SYNC_OK' : 'SYNC_WARNING',
          data: syncStatus
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
      // Step 4: 检查光柱
      currentStep++;
      const pillarStatus = await this.checkPillars();
      
      await gateway.sendProgressUpdate({
        type: MessageType.PROGRESS_UPDATE,
        requestRef,
        status: ProgressStatus.IN_PROGRESS,
        phase: 'checking_pillars',
        progress: 100,
        sourceType: 'COMMAND',
        command: {
          commandType: CommandType.SIMPLE,
          commandCode: 'CHECK_PILLARS',
          deviceType: 'pillar',
          deviceId: 'all',
          operationType: OperationType.READ,
          result: pillarStatus
        },
        report: {
          level: ReportLevel.INFO,
          message: `光柱检查完成，${pillarStatus.online}/${pillarStatus.total} 在线`
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
      // 发送最终响应
      await gateway.sendCommandResponse({
        type: MessageType.COMMAND_RESPONSE,
        requestRef,
        status: CommandStatus.COMPLETED,
        result: {
          deviceType: 'controller',
          deviceId: this.deviceId,
          commandCode: 'HealthCheck',
          operationType: OperationType.READ,
          data: {
            overallHealth: 'good',
            checksPerformed: 4,
            checksPassed: 4,
            details: {
              switchStatus,
              config,
              syncStatus,
              pillarStatus
            }
          }
        },
        report: {
          level: ReportLevel.INFO,
          message: '健康检查完成，所有系统正常'
        },
        executionTime: Date.now() - startTime,
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
    } catch (error) {
      // 错误处理
      await gateway.sendProgressUpdate({
        type: MessageType.PROGRESS_UPDATE,
        requestRef,
        status: ProgressStatus.FAILED,
        phase: 'error',
        progress: (currentStep / totalSteps) * 100,
        sourceType: 'SYSTEM',
        report: {
          level: ReportLevel.ERROR,
          message: '健康检查失败',
          code: 'HEALTH_CHECK_ERROR',
          data: {
            error: error.message,
            step: currentStep
          }
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
      // 发送失败响应
      await gateway.sendCommandResponse({
        type: MessageType.COMMAND_RESPONSE,
        requestRef,
        status: CommandStatus.FAILED,
        report: {
          level: ReportLevel.ERROR,
          message: error.message,
          code: 'HEALTH_CHECK_FAILED'
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
    }
  }
}
```

## Batch 命令进度更新

### 批量设置颜色示例

```typescript
class BatchCommandHandler {
  async executeBatchCommand(command: CommandMessage, gateway: GatewayConnection) {
    const { deviceId, parameters } = command.command;
    const devices = this.parseDeviceRange(deviceId as string); // "1-10,20-30"
    const total = devices.length;
    let completed = 0;
    let failed = 0;
    const results = [];
    
    for (const device of devices) {
      try {
        // 执行单个设备命令
        const result = await this.executeOnDevice(device, parameters);
        completed++;
        
        // 发送进度更新
        await gateway.sendProgressUpdate({
          type: MessageType.PROGRESS_UPDATE,
          requestRef: command.requestRef,
          status: ProgressStatus.IN_PROGRESS,
          phase: 'executing',
          progress: Math.round((completed / total) * 100),
          sourceType: 'COMMAND',
          command: {
            commandType: CommandType.SIMPLE,
            commandCode: command.command.commandCode,
            deviceType: command.command.deviceType,
            deviceId: device,
            operationType: command.command.operationType,
            result: result
          },
          report: {
            level: ReportLevel.INFO,
            message: `设备 ${device} 执行成功`,
            data: {
              deviceId: device,
              completed,
              total,
              failed
            }
          },
          timestamp: new Date().toISOString(),
          version: '1.0'
        });
        
        results.push({ deviceId: device, success: true, result });
        
      } catch (error) {
        failed++;
        
        // 发送错误进度更新
        await gateway.sendProgressUpdate({
          type: MessageType.PROGRESS_UPDATE,
          requestRef: command.requestRef,
          status: ProgressStatus.IN_PROGRESS,
          phase: 'executing',
          progress: Math.round(((completed + failed) / total) * 100),
          sourceType: 'COMMAND',
          command: {
            commandType: CommandType.SIMPLE,
            commandCode: command.command.commandCode,
            deviceType: command.command.deviceType,
            deviceId: device,
            operationType: command.command.operationType,
            result: { error: error.message }
          },
          report: {
            level: ReportLevel.WARNING,
            message: `设备 ${device} 执行失败: ${error.message}`,
            code: 'DEVICE_EXECUTION_FAILED',
            data: {
              deviceId: device,
              error: error.message,
              completed,
              total,
              failed
            }
          },
          timestamp: new Date().toISOString(),
          version: '1.0'
        });
        
        results.push({ deviceId: device, success: false, error: error.message });
      }
    }
    
    // 发送最终响应
    const finalStatus = failed === 0 ? CommandStatus.COMPLETED : 
                       failed < total ? CommandStatus.COMPLETED : 
                       CommandStatus.FAILED;
    
    await gateway.sendCommandResponse({
      type: MessageType.COMMAND_RESPONSE,
      requestRef: command.requestRef,
      status: finalStatus,
      result: {
        deviceType: command.command.deviceType,
        deviceId: command.command.deviceId,
        commandCode: command.command.commandCode,
        operationType: command.command.operationType,
        data: {
          summary: `批量命令执行完成`,
          targetCount: total,
          successCount: completed,
          failureCount: failed,
          results: results
        }
      },
      report: {
        level: failed === 0 ? ReportLevel.INFO : ReportLevel.WARNING,
        message: `批量命令完成: ${completed}/${total} 成功`,
        data: {
          successRate: Math.round((completed / total) * 100)
        }
      },
      executionTime: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      version: '1.0'
    });
  }
}
```

## Program 上传进度更新

### 程序上传完整流程

```typescript
class ProgramUploadHandler {
  async handleProgramUpload(program: ProgramMessage, gateway: GatewayConnection) {
    const { parameters } = program.command;
    const context: ProgramContext = {
      taskId: parameters.taskId,
      programId: parameters.programId,
      programName: parameters.programName,
      programNo: parameters.programNo,
      programType: parameters.programType
    };
    
    try {
      // Phase 1: 下载
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.DOWNLOAD,
        progress: 0,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.INFO,
          message: '开始下载节目文件...'
        }
      });
      
      const fileData = await this.downloadFile(
        parameters.downloadUrl,
        (progress) => {
          this.reportProgress(gateway, program.requestRef, {
            phase: ProgressPhase.DOWNLOAD,
            progress: progress * 0.3, // 下载占30%
            sourceType: 'SYSTEM',
            context,
            report: {
              level: ReportLevel.DEBUG,
              message: `下载进度: ${Math.round(progress * 100)}%`,
              data: {
                bytesDownloaded: progress * parameters.fileSize,
                totalBytes: parameters.fileSize
              }
            }
          });
        }
      );
      
      // Phase 2: 解压
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.DECOMPRESS,
        progress: 30,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.INFO,
          message: '正在解压文件...'
        }
      });
      
      const extractedFiles = await this.extractFiles(fileData);
      
      // Phase 3: 预处理
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.PREPROCESS,
        progress: 40,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.INFO,
          message: '正在预处理节目内容...'
        }
      });
      
      // 检查设备配置
      const deviceConfig = await this.readDeviceConfig();
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.PREPROCESS,
        progress: 45,
        sourceType: 'COMMAND',
        context,
        command: {
          commandType: CommandType.SIMPLE,
          commandCode: 'READ_DISPLAY_CONFIG',
          deviceType: 'display',
          deviceId: 1,
          operationType: OperationType.READ,
          result: deviceConfig
        },
        report: {
          level: ReportLevel.INFO,
          message: '设备配置读取完成'
        }
      });
      
      // Phase 4: 创建帧
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.FRAMES,
        progress: 50,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.INFO,
          message: '正在创建节目帧...'
        }
      });
      
      const frames = await this.createFrames(
        extractedFiles,
        deviceConfig,
        (frameProgress) => {
          this.reportProgress(gateway, program.requestRef, {
            phase: ProgressPhase.FRAMES,
            progress: 50 + frameProgress * 30, // 创建帧占30%
            sourceType: 'SYSTEM',
            context,
            report: {
              level: ReportLevel.DEBUG,
              message: `帧创建进度: ${Math.round(frameProgress * 100)}%`
            }
          });
        }
      );
      
      // Phase 5: 上传到设备
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.UPLOAD,
        progress: 80,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.INFO,
          message: '正在上传到设备...'
        }
      });
      
      const uploadResult = await this.uploadToDevice(
        frames,
        parameters.programNo,
        (uploadProgress) => {
          this.reportProgress(gateway, program.requestRef, {
            phase: ProgressPhase.UPLOAD,
            progress: 80 + uploadProgress * 15, // 上传占15%
            sourceType: 'COMMAND',
            context,
            command: {
              commandType: CommandType.SIMPLE,
              commandCode: 'WRITE_PROGRAM_DATA',
              deviceType: 'storage',
              deviceId: 1,
              operationType: OperationType.WRITE,
              result: {
                blocksWritten: Math.round(uploadProgress * 1000),
                totalBlocks: 1000
              }
            },
            report: {
              level: ReportLevel.DEBUG,
              message: `上传进度: ${Math.round(uploadProgress * 100)}%`
            }
          });
        }
      );
      
      // Phase 6: 统计
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.STATS,
        progress: 95,
        sourceType: 'COMMAND',
        context,
        command: {
          commandType: CommandType.SIMPLE,
          commandCode: 'FINALIZE_PROGRAM',
          deviceType: 'controller',
          deviceId: 1,
          operationType: OperationType.WRITE,
          result: uploadResult
        },
        report: {
          level: ReportLevel.INFO,
          message: '正在完成节目激活...'
        }
      });
      
      const stats = await this.gatherStatistics(uploadResult);
      
      // 完成
      await this.reportProgress(gateway, program.requestRef, {
        phase: ProgressPhase.STATS,
        progress: 100,
        status: ProgressStatus.COMPLETED,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.INFO,
          message: '节目上传完成',
          data: stats
        }
      });
      
      // 发送最终响应
      await gateway.sendProgramResponse({
        type: MessageType.PROGRAM_RESPONSE,
        requestRef: program.requestRef,
        status: CommandStatus.COMPLETED,
        context,
        report: {
          level: ReportLevel.INFO,
          message: '程序上传并激活成功'
        },
        executionTime: Date.now() - startTime,
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
      
    } catch (error) {
      // 错误处理
      await this.reportProgress(gateway, program.requestRef, {
        phase: this.currentPhase,
        progress: this.currentProgress,
        status: ProgressStatus.FAILED,
        sourceType: 'SYSTEM',
        context,
        report: {
          level: ReportLevel.ERROR,
          message: '程序上传失败',
          code: 'UPLOAD_FAILED',
          data: {
            error: error.message,
            phase: this.currentPhase
          }
        }
      });
      
      await gateway.sendProgramResponse({
        type: MessageType.PROGRAM_RESPONSE,
        requestRef: program.requestRef,
        status: CommandStatus.FAILED,
        context,
        report: {
          level: ReportLevel.ERROR,
          message: error.message,
          code: 'PROGRAM_UPLOAD_FAILED'
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
    }
  }
  
  private async reportProgress(
    gateway: GatewayConnection,
    requestRef: string,
    update: Partial<ProgressUpdateMessage>
  ) {
    await gateway.sendMessage({
      type: MessageType.PROGRESS_UPDATE,
      requestRef,
      status: ProgressStatus.IN_PROGRESS,
      timestamp: new Date().toISOString(),
      version: '1.0',
      ...update
    } as ProgressUpdateMessage);
  }
}
```

## 错误处理最佳实践

### 优雅的错误恢复

```typescript
class ErrorHandlingExample {
  async executeWithRetry(command: CommandMessage, gateway: GatewayConnection) {
    const maxRetries = 3;
    let attempt = 0;
    
    while (attempt < maxRetries) {
      try {
        attempt++;
        
        // 尝试执行
        const result = await this.execute(command);
        
        // 成功
        await gateway.sendProgressUpdate({
          type: MessageType.PROGRESS_UPDATE,
          requestRef: command.requestRef,
          status: ProgressStatus.COMPLETED,
          phase: 'completed',
          progress: 100,
          sourceType: 'SYSTEM',
          report: {
            level: ReportLevel.INFO,
            message: '执行成功',
            data: { attempts: attempt }
          },
          timestamp: new Date().toISOString(),
          version: '1.0'
        });
        
        return result;
        
      } catch (error) {
        // 发送警告
        await gateway.sendProgressUpdate({
          type: MessageType.PROGRESS_UPDATE,
          requestRef: command.requestRef,
          status: ProgressStatus.IN_PROGRESS,
          phase: 'retrying',
          progress: (attempt / maxRetries) * 100,
          sourceType: 'SYSTEM',
          report: {
            level: ReportLevel.WARNING,
            message: `执行失败，正在重试 (${attempt}/${maxRetries})`,
            code: 'EXECUTION_RETRY',
            data: {
              attempt,
              maxRetries,
              error: error.message
            }
          },
          timestamp: new Date().toISOString(),
          version: '1.0'
        });
        
        if (attempt >= maxRetries) {
          // 最终失败
          await gateway.sendProgressUpdate({
            type: MessageType.PROGRESS_UPDATE,
            requestRef: command.requestRef,
            status: ProgressStatus.FAILED,
            phase: 'failed',
            progress: 100,
            sourceType: 'SYSTEM',
            report: {
              level: ReportLevel.ERROR,
              message: '执行失败，已达最大重试次数',
              code: 'MAX_RETRIES_EXCEEDED',
              data: {
                attempts: attempt,
                lastError: error.message
              }
            },
            timestamp: new Date().toISOString(),
            version: '1.0'
          });
          
          throw error;
        }
        
        // 等待后重试
        await this.delay(1000 * attempt);
      }
    }
  }
}
```

## 性能监控示例

```typescript
class PerformanceMonitor {
  async executeWithMonitoring(command: CommandMessage, gateway: GatewayConnection) {
    const metrics = {
      startTime: Date.now(),
      memoryBefore: process.memoryUsage(),
      phases: new Map<string, number>()
    };
    
    // 执行并监控每个阶段
    const phases = ['init', 'process', 'finalize'];
    
    for (const phase of phases) {
      const phaseStart = Date.now();
      
      await this.executePhase(phase, command);
      
      const phaseDuration = Date.now() - phaseStart;
      metrics.phases.set(phase, phaseDuration);
      
      // 报告性能指标
      await gateway.sendProgressUpdate({
        type: MessageType.PROGRESS_UPDATE,
        requestRef: command.requestRef,
        status: ProgressStatus.IN_PROGRESS,
        phase,
        progress: ((phases.indexOf(phase) + 1) / phases.length) * 100,
        sourceType: 'SYSTEM',
        report: {
          level: ReportLevel.DEBUG,
          message: `阶段 ${phase} 完成`,
          data: {
            phaseDuration,
            totalDuration: Date.now() - metrics.startTime,
            memoryUsage: process.memoryUsage()
          }
        },
        timestamp: new Date().toISOString(),
        version: '1.0'
      });
    }
  }
}
```

## 总结

Progress Update 机制提供了灵活而强大的进度报告能力：

1. **统一的进度模型** - 适用于各种长时间操作
2. **结构化日志** - 不同级别的详细信息
3. **设备操作追踪** - 记录每个设备操作
4. **错误恢复机制** - 优雅处理错误和重试
5. **性能监控** - 实时性能指标

正确使用 Progress Update 可以：
- 提供更好的用户体验
- 便于问题诊断和调试
- 实现精细的操作控制
- 支持操作的暂停和恢复