优化逻辑

This commit is contained in:
2025-03-13 19:18:10 +08:00
parent 7a07f39f1b
commit 4189705922
14 changed files with 185 additions and 37 deletions

View File

@@ -2,6 +2,7 @@ package common
import "sync" import "sync"
// CtrlWait 待机暂停控制器
type CtrlWait struct { type CtrlWait struct {
C chan int8 C chan int8

View File

@@ -19,15 +19,15 @@ func switchPoint(ctx context.Context, point int) leaf.HandlerFunc {
switch point { switch point {
case 2: // 镇水塔点位 case 2: // 镇水塔点位
return play.OnlyVideo return play.OnlyVideo
case 5:
// 登龙云台(激光秀)
return play.LaserShow
case 10: case 10:
// 10号点位(发卡机) // 10号点位(发卡机)
return play.PushCard(ctx) return play.PushCard(ctx)
case 11: case 11:
// 11号点位(等待插卡) // 11号点位(等待插卡)
return play.WaitCard(ctx) return play.WaitCard(ctx)
case 5:
// 登龙云台(激光秀)
return play.LaserShow
default: default:
return play.Default return play.Default
} }

View File

@@ -0,0 +1,35 @@
package standby
import (
"context"
"fmt"
"game-driver/config/game"
"game-driver/internal/schema"
"game-driver/pkg/oscx"
"go.uber.org/zap"
)
func LaserShow(item schema.WaitItemModel) func(c context.Context) error {
cfg := (game.C).(game.LaserConfig)
return func(c context.Context) error {
zap.S().Infoln("开始播放大型激光秀")
o := oscx.New(cfg.Host, cfg.Port)
err := o.EnableLaserOutput()
if err != nil {
return fmt.Errorf("激光打开异常: %w", err)
} else {
defer zap.S().Infoln("大型激光秀播放结束:", item.Data)
defer o.DisableLaserOutput()
err = o.StartCue(item.Data)
if err != nil {
return fmt.Errorf("播放大型激光节目异常: %w", err)
}
}
<-c.Done()
return nil
}
}

View File

@@ -7,7 +7,6 @@ import (
"game-driver/pkg/audio" "game-driver/pkg/audio"
"game-driver/pkg/tts" "game-driver/pkg/tts"
"go.uber.org/zap" "go.uber.org/zap"
"time"
) )
func TTS(item schema.WaitItemModel) func(c context.Context) error { func TTS(item schema.WaitItemModel) func(c context.Context) error {
@@ -20,13 +19,8 @@ func TTS(item schema.WaitItemModel) func(c context.Context) error {
zap.S().Infoln("播放待机 TTS 语音") zap.S().Infoln("播放待机 TTS 语音")
defer zap.S().Infoln("结束待机 TTS 语音") defer zap.S().Infoln("结束待机 TTS 语音")
for { audio.PlayWav(c, reader)
audio.PlayWav(c, reader)
select { return nil
case <-c.Done():
return nil
case <-time.After(time.Duration(item.Interval) * time.Second):
}
}
} }
} }

View File

@@ -7,7 +7,6 @@ import (
"game-driver/pkg/utils" "game-driver/pkg/utils"
"game-driver/pkg/video" "game-driver/pkg/video"
"go.uber.org/zap" "go.uber.org/zap"
"time"
) )
func Video(item schema.WaitItemModel) func(c context.Context) error { func Video(item schema.WaitItemModel) func(c context.Context) error {
@@ -23,16 +22,10 @@ func Video(item schema.WaitItemModel) func(c context.Context) error {
utils.BlankOpen() utils.BlankOpen()
defer utils.BlankClose() defer utils.BlankClose()
for { err = video.Play(c, path, local)
err := video.Play(c, path, local) if err != nil {
if err != nil { return fmt.Errorf("视频播放异常: %w", err)
return fmt.Errorf("视频播放异常: %w", err)
}
select {
case <-c.Done():
return nil
case <-time.After(time.Duration(item.Interval) * time.Second):
}
} }
return nil
} }
} }

View File

@@ -8,8 +8,8 @@ import (
"time" "time"
) )
// Time 时间控制器 // Cron 时间控制器
func Time(rootRules []cronrange.Rule, cron string, play func(c context.Context) error) func(c context.Context) error { func Cron(rootRules []cronrange.Rule, cron string, play func(c context.Context) error) func(c context.Context) error {
// 设定默认时间规则 // 设定默认时间规则
if cron == "" { if cron == "" {
cron = "* * * *" cron = "* * * *"

View File

@@ -0,0 +1,21 @@
package standby_ctrl
import (
"context"
"game-driver/internal/common"
"go.uber.org/zap"
)
func Device(d *common.Device, lock bool, play func(c context.Context) error) func(c context.Context) error {
return func(c context.Context) error {
if lock {
zap.S().Infoln("待机任务锁定设备")
defer zap.S().Infoln("待机任务解锁设备")
d.Lock()
defer d.Unlock()
}
return play(c)
}
}

View File

@@ -0,0 +1,23 @@
package standby_ctrl
import (
"context"
"go.uber.org/zap"
"time"
)
// Duration 持续时长控制器
func Duration(duration int64, play func(c context.Context) error) func(c context.Context) error {
return func(c context.Context) error {
zap.S().Infoln("待机持续时长控制器: ", duration)
defer zap.S().Infoln("待机持续时长控制器结束: ", duration)
if duration > 0 {
ctx, cancel := context.WithTimeout(c, time.Duration(duration)*time.Second)
defer cancel()
c = ctx
}
return play(c)
}
}

View File

@@ -0,0 +1,34 @@
package standby_ctrl
import (
"context"
"go.uber.org/zap"
"time"
)
func Interval(interval int64, play func(c context.Context) error) func(c context.Context) error {
return func(c context.Context) error {
zap.S().Infoln("待机间隔控制器: ", interval)
defer zap.S().Infoln("待机间隔控制器结束: ", interval)
for {
err := play(c)
if err != nil {
zap.S().Errorln("执行后续操作异常: ", err)
}
if interval > 0 {
select {
case <-c.Done():
return nil
case <-time.After(time.Duration(interval) * time.Second):
}
} else {
select {
case <-c.Done():
return nil
default:
}
}
}
}
}

View File

@@ -13,7 +13,8 @@ import (
"sync" "sync"
) )
func WaitAction(ctrl *common.CtrlWait) leaf.HandlerFunc { // WaitAction 待机任务支持音乐、TTS、继电器、视频、网页、投影仪、大型激光秀 ctrl
func WaitAction(ctrl *common.CtrlWait, device *common.Device) leaf.HandlerFunc {
ps := common.NewPauseSub(ctrl) ps := common.NewPauseSub(ctrl)
return func(c *leaf.Context) { return func(c *leaf.Context) {
@@ -49,7 +50,15 @@ func WaitAction(ctrl *common.CtrlWait) leaf.HandlerFunc {
if f == nil { if f == nil {
return return
} }
f = standby_ctrl.Time(rules, item.Cron, f) f = standby_ctrl.Duration(item.Duration, f)
if f == nil {
return
}
f = standby_ctrl.Device(device, item.Lock, f)
if f == nil {
return
}
f = standby_ctrl.Interval(item.Interval, f)
if f == nil { if f == nil {
return return
} }
@@ -57,6 +66,10 @@ func WaitAction(ctrl *common.CtrlWait) leaf.HandlerFunc {
if f == nil { if f == nil {
return return
} }
f = standby_ctrl.Cron(rules, item.Cron, f)
if f == nil {
return
}
e := f(c) e := f(c)
if e != nil { if e != nil {
zap.S().Errorf("%s异常: %s\n", title, e) zap.S().Errorf("%s异常: %s\n", title, e)
@@ -75,9 +88,11 @@ func WaitAction(ctrl *common.CtrlWait) leaf.HandlerFunc {
case schema.WaitVideo: case schema.WaitVideo:
handleItem("视频待机控制", item, standby.Video(item)) handleItem("视频待机控制", item, standby.Video(item))
case schema.WaitWeb: case schema.WaitWeb:
handleItem("视频待机控制", item, standby.Web(item)) handleItem("网页待机控制", item, standby.Web(item))
case schema.WaitPJLink: case schema.WaitPJLink:
handleItem("视频待机控制", item, standby.PJLink(item)) handleItem("投影仪待机控制", item, standby.PJLink(item))
case schema.WaitLaserShow:
handleItem("大型激光秀控制", item, standby.LaserShow(item))
default: default:
zap.S().Infof("不支持的类型: %d\n", item.Type) zap.S().Infof("不支持的类型: %d\n", item.Type)
} }

View File

@@ -9,14 +9,17 @@ const (
WaitRelay WaitRelay
WaitWeb WaitWeb
WaitPJLink WaitPJLink
WaitLaserShow
) )
type WaitItemModel struct { type WaitItemModel struct {
Cron string `json:"cron"` Cron string `json:"cron"` // 时间规则
Type WaitType `json:"type"` Type WaitType `json:"type"` // 类型
Data string `json:"data"` Data string `json:"data"` // 执行数据
Interval int64 `json:"interval"` Duration int64 `json:"duration"` // 持续时长
Pause bool `json:"pause"` Interval int64 `json:"interval"` // 间隔时间
Pause bool `json:"pause"` // 是否暂停
Lock bool `json:"lock"` // 是否锁定
} }
type WaitModel struct { type WaitModel struct {

View File

@@ -155,7 +155,7 @@ func Run() {
middleware.PayloadJSON[schema.WaitModel](), middleware.PayloadJSON[schema.WaitModel](),
middleware.Unique(common.GlobalBgStopper), middleware.Unique(common.GlobalBgStopper),
middleware.EmergencyStop(common.GlobalBgStopper), middleware.EmergencyStop(common.GlobalBgStopper),
routes.WaitAction(common.PassCtrl), routes.WaitAction(common.PassCtrl, device),
) )
// 处理指令 // 处理指令
router.RegisterHandler(topicPrefix+"command", router.RegisterHandler(topicPrefix+"command",

27
json.md
View File

@@ -20,6 +20,24 @@ url: `server/wushan/0/play`
} }
``` ```
## 点位1击缶台
### 待机
url: `server/wushan/1/wait`
```json
{
"cron": "08:00-22:00 * * *",
"items": [
{
"type": 3,
"data": "/dev/ttyUSB0"
}
]
}
```
### Game ### Game
url: `server/wushan/1/play` url: `server/wushan/1/play`
@@ -140,7 +158,14 @@ url: `server/wushan/5/wait`
"cron": "08:00-22:00 * * *", "cron": "08:00-22:00 * * *",
"items": [ "items": [
{ {
"data": "file://./三峡龙脊BGM.mp3" "data": "file://./三峡龙脊BGM.mp3",
"pause": true
},
{
"cron": "12:05-12:10 * * *",
"type": 6,
"data": "wushan",
"lock": true
} }
] ]
} }

View File

@@ -136,10 +136,14 @@ Payload:
"cron": "17:20-21:35 1-5 * *", "cron": "17:20-21:35 1-5 * *",
// 间隔时间(s), 类型>2时, 该项无效, default 0 // 间隔时间(s), 类型>2时, 该项无效, default 0
"interval": 0, "interval": 0,
// 事件类型(0: 音频; 1: 视频; 2: TTS; 3: 继电器; 4: 网页), default 0 // 持续时长(s), 待机任务执行时持续的时长。为 0 表示 音频、视频、TTS 按播放时长,继电器、网页、投影仪、激光秀持续整个时间段。 default 0
"duration": 0,
// 事件类型(0: 音频; 1: 视频; 2: TTS; 3: 继电器; 4: 网页; 5: 投影仪; 6: 激光秀;), default 0
"type": 2, "type": 2,
// Game 指令执行时是否暂停(默认 false // Game 指令执行时是否暂停(默认 false
"pause": true, "pause": true,
// 待机任务执行时,是否锁定设备(默认 false)
"lock": false,
// 事件数据(TTS为文字, 继电器为端口号, 其他都为地址链接。支持 file:// 本地文件地址、 http(s):// 远程文件地址) // 事件数据(TTS为文字, 继电器为端口号, 其他都为地址链接。支持 file:// 本地文件地址、 http(s):// 远程文件地址)
"data": "", "data": "",
}, },