dd92845bc2
- 增加设备持久化、阻抗数据持久化、分享码持久化定时任务 - 通过环境变量 ENABLE_PERSIST_TASK 和 ENABLE_IMPEDANCE_PERSIST_TASK 控制任务启用 - 分享码配置新增最大数量和TTL时间支持多种时间单位(m/h/d) - 实现任务批量处理、锁机制及失败重试保障数据一致性 - 定时任务启动集成至服务主流程,增强系统可配置性和运维便利性 feat(ota): 新增根据设备型号和版本号查询版本名称接口 - 实现 GET /audio/getVerName 接口返回唯一 OTA 版本名称 verName - 添加请求参数校验及错误处理逻辑 - 在仓库层新增按型号和版本号查询版本名称的方法 - 完善接口文档及Swagger定义,支持前端调用查询版本名称功能
174 lines
5.0 KiB
Go
174 lines
5.0 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
"github.com/luxsin/app-api/internal/model"
|
|
)
|
|
|
|
type OTARepository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
func NewOTARepository(db *sql.DB) *OTARepository {
|
|
return &OTARepository{db: db}
|
|
}
|
|
|
|
// GetLatestOTA 按 model+hw+beta+status=1 查询最新一条 OTA 记录(verCode 降序)
|
|
func (r *OTARepository) GetLatestOTA(ctx context.Context, modelVal string, hw, beta int) (*model.OTA, error) {
|
|
const query = `SELECT id, verCode, verName, url, md5, ` + "`force`" + `, ` + "`desc`" + `, model, hw, target, beta,
|
|
startTime, endTime, status
|
|
FROM ota WHERE model = ? AND hw = ? AND beta = ? AND status = 1
|
|
ORDER BY verCode DESC LIMIT 1`
|
|
|
|
var o model.OTA
|
|
var desc, mdl sql.NullString
|
|
var startTime, endTime sql.NullTime
|
|
|
|
err := r.db.QueryRowContext(ctx, query, modelVal, hw, beta).Scan(
|
|
&o.ID, &o.VerCode, &o.VerName, &o.URL, &o.MD5, &o.Force, &desc, &mdl,
|
|
&o.HW, &o.Target, &o.Beta,
|
|
&startTime, &endTime, &o.Status,
|
|
)
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query ota: %w", err)
|
|
}
|
|
|
|
if desc.Valid {
|
|
o.Desc = &desc.String
|
|
}
|
|
if mdl.Valid {
|
|
o.Model = &mdl.String
|
|
}
|
|
if startTime.Valid {
|
|
o.StartTime = &startTime.Time
|
|
}
|
|
if endTime.Valid {
|
|
o.EndTime = &endTime.Time
|
|
}
|
|
return &o, nil
|
|
}
|
|
|
|
// GetLatestOTANotInBlackList 查询最新一条不在黑名单中的 OTA 记录
|
|
func (r *OTARepository) GetLatestOTANotInBlackList(ctx context.Context, modelVal string, hw, beta int, mac string) (*model.OTA, error) {
|
|
const query = `SELECT id, verCode, verName, url, md5, ` + "`force`" + `, ` + "`desc`" + `, model, hw, target, beta,
|
|
startTime, endTime, status
|
|
FROM ota WHERE status = 1 AND model = ? AND hw = ? AND beta = ?
|
|
AND id NOT IN (SELECT ota_id FROM black_list WHERE mac = ?)
|
|
ORDER BY verCode DESC LIMIT 1`
|
|
|
|
var o model.OTA
|
|
var desc, mdl sql.NullString
|
|
var startTime, endTime sql.NullTime
|
|
|
|
err := r.db.QueryRowContext(ctx, query, modelVal, hw, beta, mac).Scan(
|
|
&o.ID, &o.VerCode, &o.VerName, &o.URL, &o.MD5, &o.Force, &desc, &mdl,
|
|
&o.HW, &o.Target, &o.Beta,
|
|
&startTime, &endTime, &o.Status,
|
|
)
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query ota not in blacklist: %w", err)
|
|
}
|
|
|
|
if desc.Valid {
|
|
o.Desc = &desc.String
|
|
}
|
|
if mdl.Valid {
|
|
o.Model = &mdl.String
|
|
}
|
|
if startTime.Valid {
|
|
o.StartTime = &startTime.Time
|
|
}
|
|
if endTime.Valid {
|
|
o.EndTime = &endTime.Time
|
|
}
|
|
return &o, nil
|
|
}
|
|
|
|
// GetLatestOTANotTarget 查询最新一条非定向的 OTA 记录
|
|
func (r *OTARepository) GetLatestOTANotTarget(ctx context.Context, modelVal string, hw, beta int) (*model.OTA, error) {
|
|
const query = `SELECT id, verCode, verName, url, md5, ` + "`force`" + `, ` + "`desc`" + `, model, hw, target, beta,
|
|
startTime, endTime, status
|
|
FROM ota WHERE status = 1 AND model = ? AND hw = ? AND beta = ? AND target = 0
|
|
ORDER BY verCode DESC LIMIT 1`
|
|
|
|
var o model.OTA
|
|
var desc, mdl sql.NullString
|
|
var startTime, endTime sql.NullTime
|
|
|
|
err := r.db.QueryRowContext(ctx, query, modelVal, hw, beta).Scan(
|
|
&o.ID, &o.VerCode, &o.VerName, &o.URL, &o.MD5, &o.Force, &desc, &mdl,
|
|
&o.HW, &o.Target, &o.Beta,
|
|
&startTime, &endTime, &o.Status,
|
|
)
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query ota not target: %w", err)
|
|
}
|
|
|
|
if desc.Valid {
|
|
o.Desc = &desc.String
|
|
}
|
|
if mdl.Valid {
|
|
o.Model = &mdl.String
|
|
}
|
|
if startTime.Valid {
|
|
o.StartTime = &startTime.Time
|
|
}
|
|
if endTime.Valid {
|
|
o.EndTime = &endTime.Time
|
|
}
|
|
return &o, nil
|
|
}
|
|
|
|
// GetVerNameByVersion 按 model+verCode 查询版本名称
|
|
func (r *OTARepository) GetVerNameByVersion(ctx context.Context, modelVal string, version int) (string, bool, error) {
|
|
const query = `SELECT verName FROM ota WHERE model = ? AND verCode = ? LIMIT 1`
|
|
|
|
var verName string
|
|
err := r.db.QueryRowContext(ctx, query, modelVal, version).Scan(&verName)
|
|
if err == sql.ErrNoRows {
|
|
return "", false, nil
|
|
}
|
|
if err != nil {
|
|
return "", false, fmt.Errorf("query ota verName: %w", err)
|
|
}
|
|
return verName, true, nil
|
|
}
|
|
|
|
// IsInBlackList 检查 mac 是否在指定 ota_id 的黑名单中
|
|
func (r *OTARepository) IsInBlackList(ctx context.Context, otaID int, mac string) (bool, error) {
|
|
const query = `SELECT COUNT(*) FROM black_list WHERE ota_id = ? AND mac = ?`
|
|
|
|
var count int
|
|
if err := r.db.QueryRowContext(ctx, query, otaID, mac).Scan(&count); err != nil {
|
|
return false, fmt.Errorf("query black_list: %w", err)
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
// FindTargetDevice 检查 mac 是否在指定 ota_id 的定向设备中
|
|
func (r *OTARepository) FindTargetDevice(ctx context.Context, otaID int, mac string) (*model.OTATargetDevice, error) {
|
|
const query = `SELECT id, ota_id, mac_addr, create_at FROM ota_target_device WHERE ota_id = ? AND mac_addr = ?`
|
|
|
|
var d model.OTATargetDevice
|
|
err := r.db.QueryRowContext(ctx, query, otaID, mac).Scan(&d.ID, &d.OTAID, &d.MacAddr, &d.CreateAt)
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query ota_target_device: %w", err)
|
|
}
|
|
return &d, nil
|
|
}
|