Files
game-driver/internal/routes/play/push_card.go

153 lines
3.4 KiB
Go

package play
import (
"context"
"encoding/json"
"errors"
"game-driver/config/game"
"game-driver/internal/middleware"
"game-driver/internal/routes/play/card_pusher"
"game-driver/internal/schema"
"game-driver/leaf"
"game-driver/pkg/card_reader"
"game-driver/pkg/utils"
"github.com/eclipse/paho.golang/paho"
"go.uber.org/zap"
"io/fs"
"os"
"sync"
"time"
)
type ResponseBody struct {
CardId string `json:"card_id"`
Empty int `json:"empty"`
Error int `json:"error"`
OutOk int `json:"out_ok"`
num int
}
func PushCard(ctx context.Context) leaf.HandlerFunc {
g := (game.G).(game.ConfigPush)
readers := make([]card_reader.Reader, len(g.PushGroups))
devices := make([]*card_pusher.Device, len(g.PushGroups))
for i, group := range g.PushGroups {
// 解析配置
gv, _ := json.Marshal(group)
zap.S().Infof("关卡配置[%v]: %s", i, string(gv))
// 开始连接读卡器
if group.Read != "" {
reader, err := card_reader.NewReader(group.Read)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
zap.S().Errorf("读卡器串口文件不存在: %s", group.Read)
os.Exit(1)
}
zap.S().Panicf("读卡器串口 %q 连接失败 [%T]: %q", group.Read, err, err)
}
// 初始化读卡器
err = reader.Init()
if err != nil {
reader.Close()
zap.S().Panicf("读卡器 %q 初始配置失败: %s", group.Read, err)
}
// 保存读卡器
readers[i] = reader
}
// 开始连接发卡器
device, err := card_pusher.New(group)
if err != nil {
zap.S().Panicln("初始化发卡器失败: ", err)
}
// 保存发卡器
devices[i] = device
}
go func() {
<-ctx.Done()
for _, reader := range readers {
if reader != nil {
_ = reader.Close()
}
}
for _, device := range devices {
if device != nil {
_ = device.Close()
}
}
}()
return func(c *leaf.Context) {
payload := leaf.Value[*schema.PlayModal](c, middleware.PayloadJSONKey)
var action time.Duration
if a, ok := payload.Game["action"]; ok {
if v, ok := a.(float64); ok {
action = time.Duration(v)
}
}
// 等待组
var wait sync.WaitGroup
defer wait.Wait()
// 结束信号通道
a := make(chan struct{})
// 发送结束信号
defer close(a)
wait.Add(1)
go func() {
defer wait.Done()
select {
case <-a:
case <-time.After(action * time.Second):
body := &ResponseBody{}
for _, device := range devices {
body.Empty += device.GetEmpty()
body.Error += device.GetError()
}
for i, device := range devices {
if device.GetEmpty() == 0 && device.GetError() == 0 && device.GetOutOk() == 0 {
body.num = i + 1
device.PushCard()
break
}
}
// 延迟1秒获取结果并发送消息
time.AfterFunc(time.Second, func() {
if body.num != 0 {
// 若卡片就位,读取卡片信息
if devices[body.num-1].GetOutOk() == 1 && readers[body.num-1] != nil {
if info := readers[body.num-1].GetCardInfo(); info != nil {
body.CardId = info.ID
}
}
body.OutOk += devices[body.num-1].GetOutOk()
}
publishBody(ctx, c.Properties.ResponseTopic, body)
})
}
}()
// 执行等待信号
Default(c)
}
}
// 发布消息
func publishBody(ctx context.Context, topic string, body *ResponseBody) {
if topic != "" {
bytes, _ := json.Marshal(body)
utils.GlobalMqttClient.Publish(ctx, &paho.Publish{
Topic: topic,
Payload: bytes,
QoS: 1,
})
}
}