# 命令验证规则说明

## 命令接口设计

### 1. 类型安全的命令接口

为了提供编译时类型安全，我们定义了三个特定的命令接口：

```typescript
// 简单命令 - 单设备操作
interface SimpleCommand {
  commandType: CommandType.SIMPLE;  // 字面量类型，必须是 'SIMPLE'
  deviceId: number | string;        // 单个设备
  deviceType: string;               // 必需
  operationType: OperationType;     // 必需
}

// 批量命令 - 多设备操作
interface BatchCommand {
  commandType: CommandType.BATCH;   // 字面量类型，必须是 'BATCH'
  deviceId: number[] | string;      // 设备数组或范围表达式
  deviceType: string;               // 必需
  operationType: OperationType;     // 必需
}

// 复杂命令 - 系统级操作
interface ComplexCommand {
  commandType: CommandType.COMPLEX; // 字面量类型，必须是 'COMPLEX'
  deviceId?: number | number[] | string;  // 可选
  deviceType?: string;              // 可选
  operationType?: OperationType;    // 可选
}
```

### 2. 通用命令接口（GenericCommand）

用于处理运行时动态构建的命令：

```typescript
interface GenericCommand {
  commandType?: CommandType;  // 可选，默认为 SIMPLE
  deviceId?: number | number[] | string;
  deviceType?: string;
  operationType?: OperationType;
}
```

**重要**：GenericCommand 的字段都是可选的，但实际验证规则由 `MessageValidator` 在运行时根据 `commandType` 的值动态应用。

## 验证规则

### MessageValidator 的验证逻辑

```typescript
const commandType = message.command.commandType || CommandType.SIMPLE;

switch (commandType) {
  case CommandType.SIMPLE:
    // 必需: deviceType, deviceId, operationType
    // deviceId 必须是单个值（不能是数组）
    
  case CommandType.BATCH:
    // 必需: deviceType, deviceId, operationType
    // deviceId 必须是数组或字符串（范围表达式）
    
  case CommandType.COMPLEX:
    // 可选: deviceType, deviceId, operationType
}
```

### 验证示例

#### 1. SIMPLE 命令验证

```typescript
// ✅ 有效的 SIMPLE 命令
const simpleCmd: GenericCommand = {
  commandType: CommandType.SIMPLE,
  commandCode: 'LedSwitch',
  deviceId: 123,  // 单个设备
  deviceType: 'pillar',
  operationType: OperationType.WRITE
};

// ❌ 无效的 SIMPLE 命令
const invalidSimple: GenericCommand = {
  commandType: CommandType.SIMPLE,
  commandCode: 'LedSwitch',
  deviceId: [123, 124],  // 错误：SIMPLE 不支持数组
  deviceType: 'pillar',
  operationType: OperationType.WRITE
};
// 验证器会报错："SIMPLE command deviceId must be a single value"
```

#### 2. BATCH 命令验证

```typescript
// ✅ 有效的 BATCH 命令
const batchCmd: GenericCommand = {
  commandType: CommandType.BATCH,
  commandCode: 'LedSwitch',
  deviceId: [123, 124, 125],  // 设备数组
  deviceType: 'pillar',
  operationType: OperationType.WRITE
};

// ✅ 也是有效的 BATCH 命令
const batchRangeCmd: GenericCommand = {
  commandType: CommandType.BATCH,
  commandCode: 'LedSwitch',
  deviceId: '123-130',  // 范围表达式
  deviceType: 'pillar',
  operationType: OperationType.WRITE
};

// ❌ 无效的 BATCH 命令
const invalidBatch: GenericCommand = {
  commandType: CommandType.BATCH,
  commandCode: 'LedSwitch',
  deviceId: 123,  // 错误：BATCH 需要数组或字符串
  deviceType: 'pillar',
  operationType: OperationType.WRITE
};
// 验证器会报错："BATCH command deviceId must be an array or string"
```

#### 3. COMPLEX 命令验证

```typescript
// ✅ 有效的 COMPLEX 命令（最小配置）
const complexCmd: GenericCommand = {
  commandType: CommandType.COMPLEX,
  commandCode: 'SystemDiagnostics'
  // deviceId, deviceType, operationType 都是可选的
};

// ✅ 也是有效的 COMPLEX 命令（包含可选字段）
const complexCmdFull: GenericCommand = {
  commandType: CommandType.COMPLEX,
  commandCode: 'SystemReset',
  deviceId: 'all',  // 可以提供但不是必需的
  parameters: { force: true }
};
```

## 为什么这样设计？

1. **类型安全的接口（SimpleCommand, BatchCommand, ComplexCommand）**
   - 编译时类型检查
   - IDE 自动补全
   - 明确的 API 契约

2. **通用接口（GenericCommand）**
   - 处理动态构建的命令
   - 向后兼容
   - 灵活的运行时验证

3. **验证器分离**
   - 业务逻辑与类型定义分离
   - 可以轻松修改验证规则而不影响类型定义
   - 支持自定义验证逻辑

## 使用建议

1. **编写新代码时**：优先使用类型安全的接口（SimpleCommand, BatchCommand, ComplexCommand）

2. **处理外部输入时**：使用 GenericCommand + MessageValidator

3. **类型断言**：
   ```typescript
   // 验证后进行类型断言
   const result = MessageValidator.validateCommandMessage(message);
   if (result.valid && message.command.commandType === CommandType.SIMPLE) {
     const simpleCmd = message.command as SimpleCommand;
     // 现在 TypeScript 知道 deviceId 是 number | string
   }
   ```