mirror of
https://github.com/m5stack/StackChan.git
synced 2026-07-30 20:24:52 +00:00
fix(server): stabilize device bootstrap and default dance initialization
- create missing device records safely with insert-ignore - seed default dance data transactionally to avoid duplicate rows - restore real default-agent reset behavior with MAC validation - bind devices inside a transaction after ensuring the device exists
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 M5Stack Technology CO LTD
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+1030
-184
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
module stackChan
|
||||
|
||||
go 1.26.2
|
||||
go 1.26.3
|
||||
|
||||
require (
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.10.0
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.10.0/go.mod h1:6v7oGBF9wv59WERJIOJxXmLhkUcxwON3tPYW3AZ7wbY=
|
||||
github.com/gogf/gf/v2 v2.10.0/go.mod h1:Svl1N+E8G/QshU2DUbh/3J/AJauqCgUnxHurXWR4Qx0=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
|
||||
github.com/olekukonko/errors v1.2.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.1.8/go.mod h1:RPRC6UcscfFZgjo1nulkfMH5IM0QAYim0LfnMvUuozw=
|
||||
github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -81,7 +81,7 @@ var (
|
||||
})
|
||||
|
||||
// Do not use SetServerRoot, globally only provide frontend entry via /web
|
||||
//s.SetServerRoot("web/management")
|
||||
s.SetServerRoot("web/management")
|
||||
|
||||
s.SetPort(12800)
|
||||
s.Run()
|
||||
|
||||
@@ -13,12 +13,13 @@ import (
|
||||
|
||||
"stackChan/api/admin/v1"
|
||||
"stackChan/internal/dao"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"stackChan/internal/model/do"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) DeleteApp(ctx context.Context, req *v1.DeleteAppReq) (res *v1.DeleteAppRes, err error) {
|
||||
_, err = dao.AppStore.Ctx(ctx).Where("id", req.Id).Data(g.Map{"is_deleted": 1}).Update()
|
||||
_, err = dao.AppStore.Ctx(ctx).WherePri(req.Id).Data(do.AppStore{
|
||||
IsDeleted: 1,
|
||||
}).Update()
|
||||
if err != nil {
|
||||
return nil, gerror.WrapCode(gcode.CodeInternalError, err, "Failed to delete app")
|
||||
}
|
||||
|
||||
@@ -7,9 +7,8 @@ package dance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"stackChan/internal/dao"
|
||||
"stackChan/internal/model"
|
||||
"stackChan/internal/model/do"
|
||||
"stackChan/internal/service"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
@@ -24,35 +23,10 @@ func (c *ControllerV1) GetList(ctx context.Context, req *v1.GetListReq) (res *v1
|
||||
return nil, gerror.NewCode(gcode.CodeInvalidParameter)
|
||||
}
|
||||
|
||||
var danceList []model.Dance
|
||||
err = dao.DeviceDance.Ctx(ctx).Where(do.DeviceDance{
|
||||
Mac: mac,
|
||||
}).Scan(&danceList)
|
||||
danceList, err := service.GetOrCreateDanceList(ctx, mac, "file/music/stackchan_music.mp3")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Core modification: insert default data only when query result is empty
|
||||
if len(danceList) == 0 {
|
||||
// Insert single default dance data
|
||||
defaultDance := do.DeviceDance{
|
||||
Mac: mac,
|
||||
MusicUrl: "file/music/stackchan_music.mp3",
|
||||
DanceData: model.DefaultDanceData,
|
||||
}
|
||||
_, err = dao.DeviceDance.Ctx(ctx).Data(defaultDance).Insert()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Re-query list (one data exists now)
|
||||
err = dao.DeviceDance.Ctx(ctx).Where(do.DeviceDance{
|
||||
Mac: mac,
|
||||
}).Scan(&danceList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return new(v1.GetListRes(danceList)), nil
|
||||
}
|
||||
|
||||
@@ -8,43 +8,14 @@ package dance
|
||||
import (
|
||||
"context"
|
||||
"stackChan/api/dance/v2"
|
||||
"stackChan/internal/dao"
|
||||
"stackChan/internal/model"
|
||||
"stackChan/internal/model/do"
|
||||
"stackChan/internal/service"
|
||||
)
|
||||
|
||||
func (c *ControllerV2) GetList(ctx context.Context, req *v2.GetListReq) (res *v2.GetListRes, err error) {
|
||||
mac := req.Mac
|
||||
var danceList []model.Dance
|
||||
err = dao.DeviceDance.Ctx(ctx).Where(do.DeviceDance{
|
||||
Mac: mac,
|
||||
}).Scan(&danceList)
|
||||
danceList, err := service.GetOrCreateDanceList(ctx, req.Mac, "http://47.113.125.164:12800/file/music/stackchan_music.mp3")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Core modification: insert default data only when query result is empty
|
||||
if len(danceList) == 0 {
|
||||
// Insert single default dance data
|
||||
defaultDance := do.DeviceDance{
|
||||
DanceName: "StackChan Dance",
|
||||
Mac: mac,
|
||||
MusicUrl: "http://47.113.125.164:12800/file/music/stackchan_music.mp3",
|
||||
DanceData: model.DefaultDanceData,
|
||||
}
|
||||
_, err = dao.DeviceDance.Ctx(ctx).Data(defaultDance).Insert()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Re-query list (one data exists now)
|
||||
err = dao.DeviceDance.Ctx(ctx).Where(do.DeviceDance{
|
||||
Mac: mac,
|
||||
}).Scan(&danceList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return new(v2.GetListRes(danceList)), nil
|
||||
}
|
||||
|
||||
@@ -8,19 +8,22 @@ package device
|
||||
import (
|
||||
"context"
|
||||
"stackChan/api/device/v2"
|
||||
"stackChan/internal/service"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
)
|
||||
|
||||
func (c *ControllerV2) AgentRestoreDefault(ctx context.Context, req *v2.AgentRestoreDefaultReq) (res *v2.AgentRestoreDefaultRes, err error) {
|
||||
return new(v2.AgentRestoreDefaultRes(true)), err
|
||||
//if req.Mac == "" {
|
||||
// return nil, gerror.NewCode(gcode.CodeMissingParameter, "Device MAC address cannot be empty")
|
||||
//}
|
||||
//restoreResponse, err := service.RestoreDefaultAgent(req.Mac)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//if !restoreResponse {
|
||||
// return nil, gerror.NewCode(gcode.CodeInternalError, "Failed to restore default configuration")
|
||||
//}
|
||||
//return new(v2.AgentRestoreDefaultRes(true)), nil
|
||||
if req.Mac == "" {
|
||||
return nil, gerror.NewCode(gcode.CodeMissingParameter, "Device MAC address cannot be empty")
|
||||
}
|
||||
restoreResponse, err := service.RestoreDefaultAgent(req.Mac)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !restoreResponse {
|
||||
return nil, gerror.NewCode(gcode.CodeInternalError, "Failed to restore default configuration")
|
||||
}
|
||||
return new(v2.AgentRestoreDefaultRes(true)), nil
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"context"
|
||||
"stackChan/internal/dao"
|
||||
"stackChan/internal/model"
|
||||
"stackChan/internal/model/do"
|
||||
"stackChan/internal/service"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@@ -21,8 +23,6 @@ import (
|
||||
|
||||
// BindDevice Device binding interface
|
||||
func (c *ControllerV2) BindDevice(ctx context.Context, req *v2.BindDeviceReq) (res *v2.BindDeviceRes, err error) {
|
||||
// 1. Get current logged-in user UID (from context)
|
||||
_, err = service.CreateMacIfNotExists(ctx, req.Mac)
|
||||
uid := g.RequestFromCtx(ctx).GetCtxVar(model.Uid).Int64()
|
||||
if uid == 0 {
|
||||
return nil, gerror.NewCode(gcode.CodeMissingParameter, "User UID cannot be empty")
|
||||
@@ -30,10 +30,21 @@ func (c *ControllerV2) BindDevice(ctx context.Context, req *v2.BindDeviceReq) (r
|
||||
if req.Mac == "" {
|
||||
return nil, gerror.NewCode(gcode.CodeMissingParameter, "Device MAC address cannot be empty")
|
||||
}
|
||||
_, err = dao.Device.Ctx(ctx).
|
||||
Where("mac = ?", req.Mac).
|
||||
Data("uid", uid, "bind_time", gtime.Now().Format("Y-m-d H:i:s")).
|
||||
Update()
|
||||
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
if err = service.CreateMacIfNotExistsWithTx(ctx, tx, req.Mac); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dao.Device.Ctx(ctx).TX(tx).
|
||||
Where("mac = ?", req.Mac).
|
||||
Data(do.Device{
|
||||
Uid: uid,
|
||||
BindTime: gtime.Now().Format("Y-m-d H:i:s"),
|
||||
}).
|
||||
Update()
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, gerror.WrapCode(gcode.CodeDbOperationError, err, "Device binding failed")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"stackChan/internal/dao"
|
||||
"stackChan/internal/model"
|
||||
"stackChan/internal/model/do"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
const defaultDanceName = "StackChan Dance"
|
||||
|
||||
func GetOrCreateDanceList(ctx context.Context, mac string, defaultMusicURL string) (danceList []model.Dance, err error) {
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
if err = CreateMacIfNotExistsWithTx(ctx, tx, mac); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Serialize default initialization for the same device to avoid duplicate seed rows.
|
||||
if _, err = dao.Device.Ctx(ctx).TX(tx).Where("mac", mac).LockUpdate().One(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = dao.DeviceDance.Ctx(ctx).TX(tx).Where(do.DeviceDance{
|
||||
Mac: mac,
|
||||
}).Scan(&danceList); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(danceList) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err = dao.DeviceDance.Ctx(ctx).TX(tx).Data(do.DeviceDance{
|
||||
DanceName: defaultDanceName,
|
||||
Mac: mac,
|
||||
MusicUrl: defaultMusicURL,
|
||||
DanceData: model.DefaultDanceData,
|
||||
}).Insert(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeviceDance.Ctx(ctx).TX(tx).Where(do.DeviceDance{
|
||||
Mac: mac,
|
||||
}).Scan(&danceList)
|
||||
})
|
||||
return danceList, err
|
||||
}
|
||||
@@ -10,24 +10,42 @@ import (
|
||||
"stackChan/internal/dao"
|
||||
"stackChan/internal/model/do"
|
||||
"stackChan/internal/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
)
|
||||
|
||||
func CreateMacIfNotExists(ctx context.Context, mac string) (id int64, err error) {
|
||||
count, err := dao.Device.Ctx(ctx).Where("mac = ?", mac).Count()
|
||||
if err != nil {
|
||||
if err = validateMac(mac); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if count > 0 {
|
||||
return 0, nil
|
||||
}
|
||||
id, err = dao.Device.Ctx(ctx).Data(do.Device{
|
||||
Mac: mac,
|
||||
}).InsertAndGetId()
|
||||
|
||||
_, err = dao.Device.Ctx(ctx).Data(do.Device{
|
||||
Mac: mac,
|
||||
}).InsertIgnore()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return id, nil
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func CreateMacIfNotExistsWithTx(ctx context.Context, tx gdb.TX, mac string) error {
|
||||
if err := validateMac(mac); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := dao.Device.Ctx(ctx).TX(tx).Data(do.Device{
|
||||
Mac: mac,
|
||||
}).InsertIgnore()
|
||||
return err
|
||||
}
|
||||
|
||||
func validateMac(mac string) error {
|
||||
if mac == "" {
|
||||
return gerror.NewCode(gcode.CodeMissingParameter, "Device MAC address cannot be empty")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDeviceName(ctx context.Context, mac string) (name string, err error) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
2026-04-28T11:21:26.547+08:00 [INFO] {38544d753667aa188bdf205b0608ffab} xiaozhi token auto refresh ticker started, refresh cycle: 24 hours
|
||||
@@ -141,8 +141,7 @@ func Registration(ctx context.Context, req *v2.RegistrationReq) (res *v2.Registr
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
responseData := v2.RegistrationRes(remoteResp)
|
||||
return &responseData, nil
|
||||
return new(v2.RegistrationRes(remoteResp)), nil
|
||||
}
|
||||
|
||||
// callRemoteRegister Call remote registration interface
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
@@ -261,6 +262,15 @@ func GenerateFourKeys() {
|
||||
clientPrivateKey, clientPublicKey = generateKeyPair(2048)
|
||||
|
||||
// Print PEM
|
||||
//fmt.Println("=== Server Private Key ===")
|
||||
//fmt.Println(keyToPEM(serverPrivateKey, true))
|
||||
//fmt.Println("=== Server Public Key ===")
|
||||
//fmt.Println(keyToPEM(serverPublicKey, false))
|
||||
|
||||
fmt.Println("=== Client Private Key ===")
|
||||
fmt.Println(keyToPEM(clientPrivateKey, true))
|
||||
fmt.Println("=== Client Public Key ===")
|
||||
fmt.Println(keyToPEM(clientPublicKey, false))
|
||||
|
||||
// Mark initialization complete
|
||||
initialized = true
|
||||
|
||||
Reference in New Issue
Block a user