设备的部分改造
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m34s

This commit is contained in:
2026-03-10 10:34:08 +08:00
parent 86f8d0b644
commit b5147d1acb
34 changed files with 1680 additions and 485 deletions

View File

@@ -389,3 +389,127 @@ func (DeviceSimBinding) TableName() string {
- **WHEN** 开发者需要查找或修改 DeviceSimBinding 模型
- **THEN** 模型定义位于 `internal/model/device_sim_binding.go` 文件中,而非混杂在 `package.go`
---
### Requirement: Device Handler 分层修复
Device Handler SHALL 不再直接持有 `gateway.Client` 引用。所有 Gateway API 调用 SHALL 通过 Device Service 层发起。
#### Scenario: DeviceHandler 不持有 gatewayClient
- **WHEN** 创建 `DeviceHandler` 实例
- **THEN** `NewDeviceHandler` 构造函数不接收 `gateway.Client` 参数
- **AND** Handler 结构体不包含 `gatewayClient` 字段
#### Scenario: 查询设备网关信息通过 Service 调用
- **WHEN** Handler 的 `GetGatewayInfo` 方法被调用
- **THEN** Handler 调用 `service.GetGatewayInfo(ctx, identifier)`
#### Scenario: 查询设备卡槽信息通过 Service 调用
- **WHEN** Handler 的 `GetGatewaySlots` 方法被调用
- **THEN** Handler 调用 `service.GetGatewaySlots(ctx, identifier)`
#### Scenario: 设置设备限速通过 Service 调用
- **WHEN** Handler 的 `SetSpeedLimit` 方法被调用
- **THEN** Handler 调用 `service.SetGatewaySpeedLimit(ctx, identifier, speedLimit)`
#### Scenario: 设置设备 WiFi 通过 Service 调用
- **WHEN** Handler 的 `SetWiFi` 方法被调用
- **THEN** Handler 调用 `service.SetGatewayWiFi(ctx, identifier, req)`
#### Scenario: 切换设备卡通过 Service 调用
- **WHEN** Handler 的 `SwitchCard` 方法被调用
- **THEN** Handler 调用 `service.GatewaySwitchCard(ctx, identifier, targetICCID)`
#### Scenario: 重启设备通过 Service 调用
- **WHEN** Handler 的 `RebootDevice` 方法被调用
- **THEN** Handler 调用 `service.GatewayRebootDevice(ctx, identifier)`
#### Scenario: 恢复出厂设置通过 Service 调用
- **WHEN** Handler 的 `ResetDevice` 方法被调用
- **THEN** Handler 调用 `service.GatewayResetDevice(ctx, identifier)`
### Requirement: Device Service Gateway 代理方法
Device Service SHALL 提供 Gateway API 的代理方法封装设备标识符解析、IMEI 检查和 Gateway 调用。
#### Scenario: GetGatewayInfo 方法
- **WHEN** 调用 `service.GetGatewayInfo(ctx, identifier)`
- **THEN** 先通过 `GetDeviceByIdentifier` 查找设备并验证权限
- **AND** 检查设备 IMEI 不为空
- **AND** 调用 `gatewayClient.GetDeviceInfo` 传入设备 IMEI
- **AND** 返回 `*gateway.DeviceInfoResp`
#### Scenario: GetGatewaySlots 方法
- **WHEN** 调用 `service.GetGatewaySlots(ctx, identifier)`
- **THEN** 先查找设备、验证 IMEI 不为空
- **AND** 调用 `gatewayClient.GetSlotInfo`
- **AND** 返回 `*gateway.SlotInfoResp`
#### Scenario: SetGatewaySpeedLimit 方法
- **WHEN** 调用 `service.SetGatewaySpeedLimit(ctx, identifier, speedLimit)`
- **THEN** 先查找设备、验证 IMEI
- **AND** 调用 `gatewayClient.SetSpeedLimit` 传入设备 IMEI 和限速值
#### Scenario: SetGatewayWiFi 方法
- **WHEN** 调用 `service.SetGatewayWiFi(ctx, identifier, cardNo, ssid, password string, enabled bool)`
- **THEN** 先查找设备、验证 IMEI
- **AND** 调用 `gatewayClient.SetWiFi` 传入设备 IMEI、cardNoICCID、ssid、password、enabled
#### Scenario: GatewaySwitchCard 方法
- **WHEN** 调用 `service.GatewaySwitchCard(ctx, identifier, targetICCID)`
- **THEN** 先查找设备、验证 IMEI
- **AND** 调用 `gatewayClient.SwitchCard` 传入设备 IMEI 作为 cardNo 和目标 ICCID
#### Scenario: GatewayRebootDevice 方法
- **WHEN** 调用 `service.GatewayRebootDevice(ctx, identifier)`
- **THEN** 先查找设备、验证 IMEI
- **AND** 调用 `gatewayClient.RebootDevice` 传入设备 IMEI
#### Scenario: GatewayResetDevice 方法
- **WHEN** 调用 `service.GatewayResetDevice(ctx, identifier)`
- **THEN** 先查找设备、验证 IMEI
- **AND** 调用 `gatewayClient.ResetDevice` 传入设备 IMEI
#### Scenario: 设备 IMEI 为空
- **WHEN** 调用任意 Gateway 代理方法且设备的 IMEI 字段为空
- **THEN** 返回 `CodeInvalidParam` 错误
- **AND** 错误信息说明该设备未配置 IMEI
#### Scenario: 设备不存在或无权限
- **WHEN** 调用任意 Gateway 代理方法且标识符无法匹配到设备
- **THEN** 返回对应的错误(由 `GetDeviceByIdentifier` 返回)
### Requirement: Device Service 接收 Gateway Client
Device Service SHALL 在构造函数中接收 `*gateway.Client` 依赖。
#### Scenario: Device Service 初始化
- **WHEN** 创建 Device Service 实例
- **THEN** 构造函数接收 `gatewayClient *gateway.Client` 参数
- **AND** 存储为 Service 的内部字段
- **AND** `gatewayClient` 可以为 nilGateway 配置缺失时)
#### Scenario: Gateway Client 为 nil 时调用 Gateway 方法
- **WHEN** `gatewayClient` 为 nil 且调用任意 Gateway 代理方法
- **THEN** 返回 `CodeGatewayError` 错误
- **AND** 错误信息为 "Gateway 客户端未配置"