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) // 开始初始化读卡器 reader, err := card_reader.NewReader(g.ReadAddr) if err != nil { if errors.Is(err, fs.ErrNotExist) { zap.S().Errorf("读卡器串口文件不存在: %s", g.ReadAddr) os.Exit(1) } zap.S().Panicf("读卡器串口连接失败 [%T]: %q", err, err) } go func() { <-ctx.Done() _ = reader.Close() }() // 开始初始化发卡器 devices := make([]*card_pusher.Device, 0) for i, group := range g.PushGroups { // 对读卡器初始化配置 reader.SetSlave(byte(i + 1)) err = reader.Init() if err != nil { zap.S().Panicln("读卡器初始配置失败", err) } // 解析发卡器配置 gv, _ := json.Marshal(group) zap.S().Info("发卡器指针:", string(gv)) // 初始化发卡器 device, err := card_pusher.New(group) if err != nil { zap.S().Panicln("初始化发卡器失败: ", err) } devices = append(devices, device) } go func() { <-ctx.Done() for _, device := range devices { 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 { reader.SetSlave(byte(body.num)) if info := reader.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, }) } }