153 lines
3.4 KiB
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().Info("关卡配置:", 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,
|
|
})
|
|
}
|
|
}
|