package handler import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "github.com/luxsin/app-api/internal/repository" "github.com/luxsin/app-api/internal/response" "go.uber.org/zap" ) type OTAHandler struct { repo *repository.OTARepository log *zap.Logger } func NewOTAHandler(repo *repository.OTARepository, log *zap.Logger) *OTAHandler { return &OTAHandler{repo: repo, log: log} } // GetOTA 获取 OTA 升级信息 // GET /audio/ota?model=xxx&hw=1&mac=xx:xx:xx&beta=0 func (h *OTAHandler) GetOTA(c *gin.Context) { modelVal := strings.TrimSpace(c.Query("model")) hwStr := strings.TrimSpace(c.Query("hw")) mac := strings.TrimSpace(c.Query("mac")) betaStr := strings.TrimSpace(c.Query("beta")) // 参数校验 if modelVal == "" || hwStr == "" { response.BadRequest(c, "model和hw参数不能为空") return } hw, err := strconv.Atoi(hwStr) if err != nil { response.BadRequest(c, "hw参数格式错误") return } beta := 0 if betaStr != "" { if b, err := strconv.Atoi(betaStr); err == nil { beta = b } } if mac == "" { mac = "null" } ctx := c.Request.Context() // 1. 查询最新 OTA 记录 ota, err := h.repo.GetLatestOTA(ctx, modelVal, hw, beta) if err != nil { h.log.Error("query ota failed", zap.Error(err)) response.InternalError(c, "查询OTA信息失败") return } if ota == nil { response.Fail(c, http.StatusOK, 40004, "无OTA升级信息") return } // 2. 检查黑名单 inBlackList, err := h.repo.IsInBlackList(ctx, ota.ID, mac) if err != nil { h.log.Error("check black list failed", zap.Error(err)) response.InternalError(c, "查询黑名单失败") return } if inBlackList { h.log.Info("mac命中OTA黑名单", zap.String("mac", mac), zap.Int("ota_id", ota.ID)) // 命中黑名单,返回一条不在黑名单中的最新记录 ota, err = h.repo.GetLatestOTANotInBlackList(ctx, modelVal, hw, beta, mac) if err != nil { h.log.Error("query ota not in blacklist failed", zap.Error(err)) response.InternalError(c, "查询OTA信息失败") return } if ota == nil { response.Fail(c, http.StatusOK, 40004, "无OTA升级信息") return } response.OK(c, ota) return } // 3. 检查是否为定向升级 if !bool(ota.Target) { // 非定向,直接返回 response.OK(c, ota) return } // 定向升级,检查 mac 是否在定向设备列表中 targetDevice, err := h.repo.FindTargetDevice(ctx, ota.ID, mac) if err != nil { h.log.Error("check target device failed", zap.Error(err)) response.InternalError(c, "查询定向设备失败") return } if targetDevice != nil { // 定向命中,返回该 OTA response.OK(c, ota) return } // 定向未命中,返回非定向的最新版本 notTargetOTA, err := h.repo.GetLatestOTANotTarget(ctx, modelVal, hw, beta) if err != nil { h.log.Error("query ota not target failed", zap.Error(err)) response.InternalError(c, "查询OTA信息失败") return } if notTargetOTA == nil { response.Fail(c, http.StatusOK, 40004, "无OTA升级信息") return } response.OK(c, notTargetOTA) }