2025-12-04 18:44:56 +08:00
|
|
|
|
package device
|
2025-12-05 14:44:36 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
2025-12-05 16:53:52 +08:00
|
|
|
|
"fmt"
|
|
|
|
|
|
"path/filepath"
|
|
|
|
|
|
"time"
|
2025-12-05 14:44:36 +08:00
|
|
|
|
|
2025-12-05 16:53:52 +08:00
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
2025-12-05 14:44:36 +08:00
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
|
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
2025-12-05 16:53:52 +08:00
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/utils/file"
|
2025-12-05 14:44:36 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// otaServiceImpl 是 OtaService 接口的实现。
|
|
|
|
|
|
type otaServiceImpl struct {
|
2025-12-05 16:53:52 +08:00
|
|
|
|
ctx context.Context
|
2025-12-05 14:44:36 +08:00
|
|
|
|
otaRepo repository.OtaRepository
|
|
|
|
|
|
deviceRepo repository.DeviceRepository
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewOtaService 创建一个新的 OtaService 实例。
|
2025-12-05 16:53:52 +08:00
|
|
|
|
func NewOtaService(ctx context.Context, otaRepo repository.OtaRepository, deviceRepo repository.DeviceRepository) OtaService {
|
2025-12-05 14:44:36 +08:00
|
|
|
|
return &otaServiceImpl{
|
2025-12-05 16:53:52 +08:00
|
|
|
|
ctx: ctx,
|
2025-12-05 14:44:36 +08:00
|
|
|
|
otaRepo: otaRepo,
|
|
|
|
|
|
deviceRepo: deviceRepo,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-05 16:08:06 +08:00
|
|
|
|
func (o *otaServiceImpl) StartUpgrade(ctx context.Context, areaControllerID uint32, firmwarePath string) (uint32, error) {
|
2025-12-05 14:44:36 +08:00
|
|
|
|
//TODO implement me
|
|
|
|
|
|
panic("implement me")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-05 16:08:06 +08:00
|
|
|
|
func (o *otaServiceImpl) GetUpgradeProgress(ctx context.Context, taskID uint32) (executed, total uint32, CurrentStage models.OTATaskStatus, err error) {
|
2025-12-05 14:44:36 +08:00
|
|
|
|
//TODO implement me
|
|
|
|
|
|
panic("implement me")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (o *otaServiceImpl) StopUpgrade(ctx context.Context, taskID uint32) error {
|
2025-12-05 16:53:52 +08:00
|
|
|
|
serviceCtx, logger := logs.Trace(ctx, o.ctx, "StopUpgrade")
|
|
|
|
|
|
|
|
|
|
|
|
task, err := o.otaRepo.FindByID(serviceCtx, taskID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
logger.Errorf("查找 OTA 任务失败: %v, 任务ID: %d", err, taskID)
|
|
|
|
|
|
return fmt.Errorf("查找 OTA 任务失败: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 幂等性检查:如果任务已处于终态,则直接返回成功
|
|
|
|
|
|
if task.IsOver() {
|
|
|
|
|
|
logger.Infof("OTA 任务 %d 已处于终态 %s,无需停止", taskID, task.Status)
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
|
|
task.Status = models.OTATaskStatusStopped
|
|
|
|
|
|
task.CompletedAt = &now
|
|
|
|
|
|
task.ErrorMessage = "任务被用户手动停止"
|
|
|
|
|
|
|
|
|
|
|
|
if err := o.otaRepo.Update(serviceCtx, task); err != nil {
|
|
|
|
|
|
logger.Errorf("更新 OTA 任务状态失败: %v, 任务ID: %d", err, taskID)
|
|
|
|
|
|
return fmt.Errorf("更新 OTA 任务状态失败: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清理相关文件目录
|
|
|
|
|
|
dirToRemove := filepath.Join(models.OTADir, fmt.Sprintf("%d", taskID))
|
|
|
|
|
|
if err := file.RemoveTempDir(dirToRemove); err != nil {
|
|
|
|
|
|
// 文件清理失败不应阻塞主流程,但需要记录日志
|
|
|
|
|
|
logger.Warnf("清理 OTA 任务 %d 的文件目录 %s 失败: %v", taskID, dirToRemove, err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logger.Infof("OTA 任务 %d 已被成功标记为手动停止", taskID)
|
|
|
|
|
|
return nil
|
2025-12-05 14:44:36 +08:00
|
|
|
|
}
|