Compare commits
6 Commits
v1.0.2-rc2
...
v1.0.2-rc3
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f527dce98 | |||
| cbccb07398 | |||
| b0f07624b0 | |||
| e31fca22c8 | |||
| bee3b98798 | |||
| e4c34f0eec |
@@ -23,9 +23,9 @@ steps:
|
|||||||
- apt-get install -y libasound2-dev:arm64 libvlc-dev:arm64
|
- apt-get install -y libasound2-dev:arm64 libvlc-dev:arm64
|
||||||
- mkdir -p release
|
- mkdir -p release
|
||||||
# 构建 amd64 (native)
|
# 构建 amd64 (native)
|
||||||
- PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig go build -ldflags="-w -s" -o release/game-driver-linux-amd64 .
|
- PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig go build -ldflags="-w -s -X main.Version=${CI_COMMIT_TAG} -X main.Commit=${CI_COMMIT_SHA}" -o release/game-driver-linux-amd64 .
|
||||||
# 构建 arm64 (cross-compile)
|
# 构建 arm64 (cross-compile)
|
||||||
- PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go build -ldflags="-w -s" -o release/game-driver-linux-arm64 .
|
- PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go build -ldflags="-w -s -X main.Version=${CI_COMMIT_TAG} -X main.Commit=${CI_COMMIT_SHA}" -o release/game-driver-linux-arm64 .
|
||||||
- ls -lh release/
|
- ls -lh release/
|
||||||
|
|
||||||
# 发布构建产物(可选)
|
# 发布构建产物(可选)
|
||||||
|
|||||||
90
cmd/root.go
90
cmd/root.go
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright © 2024 慕枫Go <mapleafgo@163.com>
|
|
||||||
*/
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"game-driver/config"
|
|
||||||
"game-driver/config/game"
|
|
||||||
"game-driver/config/wait"
|
|
||||||
"game-driver/internal"
|
|
||||||
"io/fs"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
var cfgFile string
|
|
||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
|
||||||
var rootCmd = &cobra.Command{
|
|
||||||
Use: "game-driver",
|
|
||||||
Version: "1.0.1",
|
|
||||||
Short: "A brief description of your application",
|
|
||||||
Long: `A longer description that spans multiple lines and likely contains
|
|
||||||
examples and usage of using your application. For example:
|
|
||||||
|
|
||||||
Cobra is a CLI library for Go that empowers applications.
|
|
||||||
This application is a tool to generate the needed files
|
|
||||||
to quickly create a Cobra application.`,
|
|
||||||
// Uncomment the following line if your bare application
|
|
||||||
// has an action associated with it:
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
internal.Run()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
|
||||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
|
||||||
func Execute() {
|
|
||||||
err := rootCmd.Execute()
|
|
||||||
if err != nil {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cobra.OnInitialize(initConfig)
|
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "config.yml", "默认当前目录下的 config.yml")
|
|
||||||
}
|
|
||||||
|
|
||||||
// initConfig reads in config file and ENV variables if set.
|
|
||||||
func initConfig() {
|
|
||||||
viper.SetConfigFile(cfgFile)
|
|
||||||
viper.AutomaticEnv() // read in environment variables that match
|
|
||||||
// If a config file is found, read it in.
|
|
||||||
if err := viper.ReadInConfig(); err == nil {
|
|
||||||
log.Printf("Using config file: %s", viper.ConfigFileUsed())
|
|
||||||
} else if errors.Is(err, fs.ErrNotExist) {
|
|
||||||
log.Printf("无法找到主配置文件: %s", viper.ConfigFileUsed())
|
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
|
||||||
log.Panicln("read config file error: ", err)
|
|
||||||
}
|
|
||||||
err := viper.Unmarshal(&config.C)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicln("unmarshal config failed: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化游戏节点配置
|
|
||||||
game.C = game.NewConfig(config.C.Point)
|
|
||||||
if game.C != nil { // 如果需要游戏配置
|
|
||||||
err = viper.UnmarshalKey("game", &game.C)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicln("unmarshal game config failed: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化游戏节点待机时配置
|
|
||||||
wait.C = wait.NewConfig(config.C.Point)
|
|
||||||
if wait.C != nil { // 如果需要游戏配置
|
|
||||||
err = viper.UnmarshalKey("wait", &wait.C)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicln("unmarshal wait config failed: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
31
go.mod
31
go.mod
@@ -11,9 +11,9 @@ require (
|
|||||||
github.com/gopxl/beep/v2 v2.1.1
|
github.com/gopxl/beep/v2 v2.1.1
|
||||||
github.com/grid-x/modbus v0.0.0-20250219144522-2b18d136199f
|
github.com/grid-x/modbus v0.0.0-20250219144522-2b18d136199f
|
||||||
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5
|
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/viper v1.21.0
|
||||||
github.com/spf13/viper v1.19.0
|
|
||||||
github.com/tencentcloud/tencentcloud-cls-sdk-go v1.0.11
|
github.com/tencentcloud/tencentcloud-cls-sdk-go v1.0.11
|
||||||
|
github.com/urfave/cli/v3 v3.8.0
|
||||||
github.com/warthog618/go-gpiocdev v0.9.1
|
github.com/warthog618/go-gpiocdev v0.9.1
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
@@ -21,33 +21,31 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.93 // indirect
|
github.com/aliyun/alibaba-cloud-sdk-go v1.63.93 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/ebitengine/oto/v3 v3.3.2 // indirect
|
github.com/ebitengine/oto/v3 v3.3.2 // indirect
|
||||||
github.com/ebitengine/purego v0.8.2 // indirect
|
github.com/ebitengine/purego v0.8.2 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect
|
github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect
|
||||||
github.com/hajimehoshi/go-mp3 v0.3.4 // indirect
|
github.com/hajimehoshi/go-mp3 v0.3.4 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.9 // indirect
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||||
github.com/satori/go.uuid v1.2.0 // indirect
|
github.com/satori/go.uuid v1.2.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||||
github.com/spf13/afero v1.12.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/spf13/cast v1.7.1 // indirect
|
github.com/spf13/cast v1.10.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.6 // indirect
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/ysmood/fetchup v0.3.0 // indirect
|
github.com/ysmood/fetchup v0.3.0 // indirect
|
||||||
github.com/ysmood/goob v0.4.0 // indirect
|
github.com/ysmood/goob v0.4.0 // indirect
|
||||||
@@ -56,11 +54,10 @@ require (
|
|||||||
github.com/ysmood/leakless v0.9.0 // indirect
|
github.com/ysmood/leakless v0.9.0 // indirect
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/net v0.37.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.5 // indirect
|
google.golang.org/protobuf v1.36.5 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
62
go.sum
62
go.sum
@@ -9,7 +9,6 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.63.93 h1:yHRWq/QmBJ3lC15zy1A1+TkvcAN+6
|
|||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.93/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
github.com/aliyun/alibaba-cloud-sdk-go v1.63.93/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||||
github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1 h1:LjItoNZuu5xHlsByFo+kr3nGa4LRIESCGWhfurayxBg=
|
github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1 h1:LjItoNZuu5xHlsByFo+kr3nGa4LRIESCGWhfurayxBg=
|
||||||
github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1/go.mod h1:4BDMUKpEaP/Ct79w0ozR0nbnEj49g1k3mrgX/IKG5I4=
|
github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1/go.mod h1:4BDMUKpEaP/Ct79w0ozR0nbnEj49g1k3mrgX/IKG5I4=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -25,13 +24,15 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/
|
|||||||
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-pkgz/cronrange v0.2.0 h1:FaJ/TB7Ng3xTCfRgblfLecL07RccXVVB6+/hdFaGbBE=
|
github.com/go-pkgz/cronrange v0.2.0 h1:FaJ/TB7Ng3xTCfRgblfLecL07RccXVVB6+/hdFaGbBE=
|
||||||
github.com/go-pkgz/cronrange v0.2.0/go.mod h1:2dPQzEVkSwXsRdcGFXIE6xllAnwELWUusad2MyVskLs=
|
github.com/go-pkgz/cronrange v0.2.0/go.mod h1:2dPQzEVkSwXsRdcGFXIE6xllAnwELWUusad2MyVskLs=
|
||||||
github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA=
|
github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA=
|
||||||
github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg=
|
github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg=
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
@@ -56,12 +57,8 @@ github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa/go.mod h1:kdOd86/VGF
|
|||||||
github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68=
|
github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68=
|
||||||
github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo=
|
github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo=
|
||||||
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
|
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
|
||||||
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5 h1:fqwINudmUrvGCuw+e3tedZ2UJ0hklSw6t8UPomctKyQ=
|
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5 h1:fqwINudmUrvGCuw+e3tedZ2UJ0hklSw6t8UPomctKyQ=
|
||||||
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5/go.mod h1:lqMjoCs0y0GoRRujSPZRBaGb4c5ER6TfkFKSClxkMbY=
|
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5/go.mod h1:lqMjoCs0y0GoRRujSPZRBaGb4c5ER6TfkFKSClxkMbY=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
@@ -83,10 +80,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
|
||||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -99,8 +92,8 @@ github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:Ff
|
|||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||||
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
|
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
|
||||||
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
|
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
@@ -111,32 +104,27 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
|||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
|
||||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
|
||||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
github.com/tencentcloud/tencentcloud-cls-sdk-go v1.0.11 h1:LJshkcQ14A/7XCgqalheBHv8qLwwOXr/xqttQbjWdHM=
|
github.com/tencentcloud/tencentcloud-cls-sdk-go v1.0.11 h1:LJshkcQ14A/7XCgqalheBHv8qLwwOXr/xqttQbjWdHM=
|
||||||
@@ -145,6 +133,8 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO
|
|||||||
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||||
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
|
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
|
||||||
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||||
|
github.com/urfave/cli/v3 v3.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI=
|
||||||
|
github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
|
||||||
github.com/warthog618/go-gpiocdev v0.9.1 h1:pwHPaqjJfhCipIQl78V+O3l9OKHivdRDdmgXYbmhuCI=
|
github.com/warthog618/go-gpiocdev v0.9.1 h1:pwHPaqjJfhCipIQl78V+O3l9OKHivdRDdmgXYbmhuCI=
|
||||||
github.com/warthog618/go-gpiocdev v0.9.1/go.mod h1:dN3e3t/S2aSNC+hgigGE/dBW8jE1ONk9bDSEYfoPyl8=
|
github.com/warthog618/go-gpiocdev v0.9.1/go.mod h1:dN3e3t/S2aSNC+hgigGE/dBW8jE1ONk9bDSEYfoPyl8=
|
||||||
github.com/warthog618/go-gpiosim v0.1.1 h1:MRAEv+T+itmw+3GeIGpQJBfanUVyg0l3JCTwHtwdre4=
|
github.com/warthog618/go-gpiosim v0.1.1 h1:MRAEv+T+itmw+3GeIGpQJBfanUVyg0l3JCTwHtwdre4=
|
||||||
@@ -172,6 +162,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@@ -179,8 +171,6 @@ golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL
|
|||||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
|
||||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
@@ -199,8 +189,8 @@ golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import (
|
|||||||
"game-driver/leaf"
|
"game-driver/leaf"
|
||||||
"game-driver/pkg/audio"
|
"game-driver/pkg/audio"
|
||||||
"game-driver/pkg/utils"
|
"game-driver/pkg/utils"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/gopxl/beep/v2/speaker"
|
"github.com/gopxl/beep/v2/speaker"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PlayBgm 播放背景音乐
|
// PlayBgm 播放背景音乐
|
||||||
@@ -44,15 +45,11 @@ func PlayBgm() leaf.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
<-a
|
||||||
case <-a:
|
|
||||||
{
|
|
||||||
speaker.Lock()
|
speaker.Lock()
|
||||||
ctrl.Streamer = nil
|
ctrl.Streamer = nil
|
||||||
speaker.Unlock()
|
speaker.Unlock()
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
zap.S().Infoln("未解析到背景音乐")
|
zap.S().Infoln("未解析到背景音乐")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func SoundStart() leaf.HandlerFunc {
|
|||||||
|
|
||||||
// 使用请求的 context,支持取消和超时
|
// 使用请求的 context,支持取消和超时
|
||||||
if pm.TTS.Start != "" {
|
if pm.TTS.Start != "" {
|
||||||
tts.DefaultTTS.SoundWithContext(c, pm.TTS.Start)
|
tts.DefaultTTS.Sound(c, pm.TTS.Start)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -27,7 +27,7 @@ func SoundStart() leaf.HandlerFunc {
|
|||||||
text = pm.TTS.Stop
|
text = pm.TTS.Stop
|
||||||
}
|
}
|
||||||
if text != "" {
|
if text != "" {
|
||||||
tts.DefaultTTS.SoundWithContext(c, text)
|
tts.DefaultTTS.Sound(c, text)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"game-driver/internal/schema"
|
"game-driver/internal/schema"
|
||||||
"game-driver/leaf"
|
"game-driver/leaf"
|
||||||
"game-driver/pkg/tts"
|
"game-driver/pkg/tts"
|
||||||
@@ -34,7 +35,7 @@ func TickerAction() leaf.HandlerFunc {
|
|||||||
defer close(a)
|
defer close(a)
|
||||||
|
|
||||||
wait.Add(1)
|
wait.Add(1)
|
||||||
go func() {
|
go func(ctx context.Context) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer wait.Done()
|
defer wait.Done()
|
||||||
// 定时器
|
// 定时器
|
||||||
@@ -48,6 +49,9 @@ func TickerAction() leaf.HandlerFunc {
|
|||||||
select {
|
select {
|
||||||
case <-a:
|
case <-a:
|
||||||
over = true
|
over = true
|
||||||
|
case <-ctx.Done():
|
||||||
|
zap.S().Infoln("Ticker 计时被取消")
|
||||||
|
over = true
|
||||||
case m := <-ticker.C:
|
case m := <-ticker.C:
|
||||||
{
|
{
|
||||||
s := int(m.Sub(start).Seconds())
|
s := int(m.Sub(start).Seconds())
|
||||||
@@ -55,12 +59,12 @@ func TickerAction() leaf.HandlerFunc {
|
|||||||
//TODO: 屏幕打印
|
//TODO: 屏幕打印
|
||||||
}
|
}
|
||||||
if to, ok := ttsMap[s]; ok {
|
if to, ok := ttsMap[s]; ok {
|
||||||
tts.DefaultTTS.Sound(to.Value)
|
tts.DefaultTTS.Sound(ctx, to.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}(c)
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ func OnlyVideo(c *leaf.Context) {
|
|||||||
zap.S().Errorln("视频文件获取异常: ", err)
|
zap.S().Errorln("视频文件获取异常: ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = video.Play(c, path, local)
|
if err := video.Play(c, path, local); err != nil {
|
||||||
|
zap.S().Errorln("视频播放异常: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import (
|
|||||||
"game-driver/pkg/card_reader"
|
"game-driver/pkg/card_reader"
|
||||||
"game-driver/pkg/channel"
|
"game-driver/pkg/channel"
|
||||||
"game-driver/pkg/tts"
|
"game-driver/pkg/tts"
|
||||||
"go.uber.org/zap"
|
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WaitCard(ctx context.Context) leaf.HandlerFunc {
|
func WaitCard(ctx context.Context) leaf.HandlerFunc {
|
||||||
@@ -79,13 +80,14 @@ func WaitCard(ctx context.Context) leaf.HandlerFunc {
|
|||||||
defer cardInfo.Close()
|
defer cardInfo.Close()
|
||||||
|
|
||||||
// 结束信号通道
|
// 结束信号通道
|
||||||
cc, cancel := context.WithCancel(context.TODO())
|
// 使用独立 context 确保读卡器监听完整执行,不受外部取消影响
|
||||||
|
c2, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
wait.Add(1)
|
wait.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wait.Done()
|
defer wait.Done()
|
||||||
reader.OnCardInfo(cc, func(info *card_reader.CardInfo) {
|
reader.OnCardInfo(c2, func(info *card_reader.CardInfo) {
|
||||||
cardInfo.Send(info.ID)
|
cardInfo.Send(info.ID)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
@@ -103,12 +105,12 @@ func WaitCard(ctx context.Context) leaf.HandlerFunc {
|
|||||||
if cardId != id {
|
if cardId != id {
|
||||||
zap.S().Infof("读取到卡片数据%q,与预期卡片数据%q不一致", id, cardId)
|
zap.S().Infof("读取到卡片数据%q,与预期卡片数据%q不一致", id, cardId)
|
||||||
// 播报错误提示
|
// 播报错误提示
|
||||||
tts.DefaultTTS.Sound(cardError)
|
tts.DefaultTTS.Sound(c, cardError)
|
||||||
isNeed = true
|
isNeed = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// 播报恭喜语音
|
// 播报恭喜语音
|
||||||
tts.DefaultTTS.Sound(cardOk)
|
tts.DefaultTTS.Sound(c, cardOk)
|
||||||
//TODO: 打开炫酷光效,屏幕跳转恭喜页面
|
//TODO: 打开炫酷光效,屏幕跳转恭喜页面
|
||||||
zap.S().Infof("读取到卡片数据%q,开始打开炫酷光效", id)
|
zap.S().Infof("读取到卡片数据%q,开始打开炫酷光效", id)
|
||||||
Default(c)
|
Default(c)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func TTS(item schema.WaitItemModel) func(c context.Context) error {
|
func TTS(item schema.WaitItemModel) func(c context.Context) error {
|
||||||
return func(c context.Context) error {
|
return func(c context.Context) error {
|
||||||
reader, err := tts.DefaultTTS.Get(item.Data)
|
reader, err := tts.DefaultTTS.Get(c, item.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("语音合成异常: %w", err)
|
return fmt.Errorf("语音合成异常: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ func Cron(rootRules []cronrange.Rule, cron string, play func(c context.Context)
|
|||||||
case r := <-a:
|
case r := <-a:
|
||||||
if r {
|
if r {
|
||||||
if ok := m.TryLock(); ok {
|
if ok := m.TryLock(); ok {
|
||||||
ctx, cc := context.WithCancel(context.TODO())
|
// 使用独立 context 确保任务完整执行,不受外部取消影响
|
||||||
|
ctx, cc := context.WithCancel(context.Background())
|
||||||
cancel = cc
|
cancel = cc
|
||||||
waitGroup.Add(1)
|
waitGroup.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ func Interval(interval int64, play func(c context.Context) error) func(c context
|
|||||||
case <-c.Done():
|
case <-c.Done():
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
|
// 避免忙循环,短暂休眠
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"game-driver/internal/common"
|
"game-driver/internal/common"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pause 暂停控制器
|
// Pause 暂停控制器
|
||||||
@@ -58,6 +59,8 @@ func Pause(ps *common.PauseSub, isPause bool, play func(c context.Context) error
|
|||||||
zap.S().Infoln("执行后续操作异常: ", err)
|
zap.S().Infoln("执行后续操作异常: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 避免忙循环,短暂休眠
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ func Run() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 构建语音合成对象
|
// 构建语音合成对象
|
||||||
tts.DefaultTTS = tts.New(ctx, config.C.Aliyun)
|
tts.DefaultTTS = tts.New(config.C.Aliyun)
|
||||||
|
|
||||||
// 构建继电器对象
|
// 构建继电器对象
|
||||||
var r relay.Relay
|
var r relay.Relay
|
||||||
@@ -143,9 +143,9 @@ func Run() {
|
|||||||
middleware.DeviceLock(device),
|
middleware.DeviceLock(device),
|
||||||
middleware.PauseWait(common.PassCtrl),
|
middleware.PauseWait(common.PassCtrl),
|
||||||
middleware.EmergencyStop(common.GlobalStopper),
|
middleware.EmergencyStop(common.GlobalStopper),
|
||||||
|
middleware.TimeoutOver(config.C.MaxTimeout),
|
||||||
middleware.SoundStart(),
|
middleware.SoundStart(),
|
||||||
middleware.RelayMaster(r),
|
middleware.RelayMaster(r),
|
||||||
middleware.TimeoutOver(config.C.MaxTimeout),
|
|
||||||
middleware.TickerAction(),
|
middleware.TickerAction(),
|
||||||
middleware.PlayBgm(),
|
middleware.PlayBgm(),
|
||||||
routes.PlayRouter(ctx, config.C.Location, config.C.Point),
|
routes.PlayRouter(ctx, config.C.Location, config.C.Point),
|
||||||
|
|||||||
95
main.go
95
main.go
@@ -3,8 +3,99 @@ Copyright © 2024 慕枫Go <mapleafgo@163.com>
|
|||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "game-driver/cmd"
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"game-driver/config"
|
||||||
|
"game-driver/config/game"
|
||||||
|
"game-driver/config/wait"
|
||||||
|
"game-driver/internal"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 版本信息,编译时通过 ldflags 注入
|
||||||
|
var (
|
||||||
|
Version = "dev"
|
||||||
|
Commit = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
// formatVersion 格式化版本信息
|
||||||
|
func formatVersion() string {
|
||||||
|
if Commit == "unknown" {
|
||||||
|
return Version
|
||||||
|
}
|
||||||
|
if len(Commit) > 7 {
|
||||||
|
return Version + " (" + Commit[:7] + ")"
|
||||||
|
}
|
||||||
|
return Version + " (" + Commit + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// initConfig 读取配置文件和环境变量
|
||||||
|
func initConfig(cfgFile string) error {
|
||||||
|
viper.SetConfigFile(cfgFile)
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
|
||||||
|
// 读取配置文件
|
||||||
|
if err := viper.ReadInConfig(); err == nil {
|
||||||
|
log.Printf("使用配置文件: %s", viper.ConfigFileUsed())
|
||||||
|
} else if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return fmt.Errorf("配置文件不存在: %s", cfgFile)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("读取配置文件错误: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析主配置
|
||||||
|
if err := viper.Unmarshal(&config.C); err != nil {
|
||||||
|
return fmt.Errorf("解析主配置失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析游戏配置
|
||||||
|
if game.C = game.NewConfig(config.C.Point); game.C != nil {
|
||||||
|
if err := viper.UnmarshalKey("game", &game.C); err != nil {
|
||||||
|
return fmt.Errorf("解析游戏配置失败: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析待机配置
|
||||||
|
if wait.C = wait.NewConfig(config.C.Point); wait.C != nil {
|
||||||
|
if err := viper.UnmarshalKey("wait", &wait.C); err != nil {
|
||||||
|
return fmt.Errorf("解析待机配置失败: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
app := &cli.Command{
|
||||||
|
Name: "game-driver",
|
||||||
|
Usage: "游戏驱动程序",
|
||||||
|
Version: formatVersion(),
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "config",
|
||||||
|
Aliases: []string{"c"},
|
||||||
|
Value: "config.yml",
|
||||||
|
Usage: "配置文件路径",
|
||||||
|
Sources: cli.EnvVars("CONFIG_FILE"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Before: func(ctx context.Context, cmd *cli.Command) (context.Context, error) {
|
||||||
|
return ctx, initConfig(cmd.String("config"))
|
||||||
|
},
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
internal.Run()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.Run(context.Background(), os.Args); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package audio
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gopxl/beep/v2"
|
"github.com/gopxl/beep/v2"
|
||||||
"github.com/gopxl/beep/v2/mp3"
|
"github.com/gopxl/beep/v2/mp3"
|
||||||
"github.com/gopxl/beep/v2/speaker"
|
"github.com/gopxl/beep/v2/speaker"
|
||||||
"github.com/gopxl/beep/v2/wav"
|
"github.com/gopxl/beep/v2/wav"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultSampleRate = beep.SampleRate(44100)
|
var DefaultSampleRate = beep.SampleRate(44100)
|
||||||
@@ -30,7 +31,11 @@ func PlayWav(c context.Context, r io.Reader) {
|
|||||||
}
|
}
|
||||||
defer streamer.Close()
|
defer streamer.Close()
|
||||||
|
|
||||||
zap.S().Debugln("WAV解码成功,采样率:", format.SampleRate)
|
// 获取音频长度信息
|
||||||
|
totalSamples := streamer.Len()
|
||||||
|
zap.S().Debugf("WAV解码成功,采样率: %d, 总样本数: %d, 预计时长: %.2f秒",
|
||||||
|
format.SampleRate, totalSamples, float64(totalSamples)/float64(format.SampleRate))
|
||||||
|
|
||||||
s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer)
|
s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer)
|
||||||
|
|
||||||
ctrl := &beep.Ctrl{Streamer: s}
|
ctrl := &beep.Ctrl{Streamer: s}
|
||||||
@@ -41,18 +46,32 @@ func PlayWav(c context.Context, r io.Reader) {
|
|||||||
})))
|
})))
|
||||||
|
|
||||||
zap.S().Debugln("等待音频播放完成...")
|
zap.S().Debugln("等待音频播放完成...")
|
||||||
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
lastPos := 0
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
zap.S().Infoln("音频播放正常结束")
|
zap.S().Infoln("音频播放正常结束")
|
||||||
return
|
return
|
||||||
case <-c.Done():
|
case <-c.Done():
|
||||||
{
|
zap.S().Debugf("音频播放被 context 取消: %v", c.Err())
|
||||||
zap.S().Infoln("音频播放被 context 取消")
|
|
||||||
speaker.Lock()
|
speaker.Lock()
|
||||||
ctrl.Streamer = nil
|
ctrl.Streamer = nil
|
||||||
speaker.Unlock()
|
speaker.Unlock()
|
||||||
return
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
// 获取当前播放位置
|
||||||
|
pos := streamer.Position()
|
||||||
|
if pos != lastPos {
|
||||||
|
progress := float64(pos) / float64(totalSamples) * 100
|
||||||
|
currentTime := float64(pos) / float64(format.SampleRate)
|
||||||
|
zap.S().Debugf("播放进度: %d/%d (%.1f%%), %.2f秒", pos, totalSamples, progress, currentTime)
|
||||||
|
lastPos = pos
|
||||||
|
} else {
|
||||||
|
zap.S().Debugf("播放停滞在位置: %d/%d, Streamer状态: %v",
|
||||||
|
pos, totalSamples, ctrl.Streamer != nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,12 +98,10 @@ func PlayMP3(c context.Context, r io.ReadCloser) {
|
|||||||
case <-done:
|
case <-done:
|
||||||
return
|
return
|
||||||
case <-c.Done():
|
case <-c.Done():
|
||||||
{
|
|
||||||
speaker.Lock()
|
speaker.Lock()
|
||||||
ctrl.Streamer = nil
|
ctrl.Streamer = nil
|
||||||
speaker.Unlock()
|
speaker.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package errorsx
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var DriverTimeoutErr = errors.New("处理超时")
|
|
||||||
|
|
||||||
var DriverCancelErr = errors.New("系统取消")
|
|
||||||
|
|
||||||
var ThirdPartyErr = errors.New("第三方请求异常")
|
|
||||||
@@ -7,19 +7,21 @@ import (
|
|||||||
"game-driver/config"
|
"game-driver/config"
|
||||||
"game-driver/leaf"
|
"game-driver/leaf"
|
||||||
"game-driver/pkg/audio"
|
"game-driver/pkg/audio"
|
||||||
"game-driver/pkg/errorsx"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
nls "github.com/aliyun/alibabacloud-nls-go-sdk"
|
nls "github.com/aliyun/alibabacloud-nls-go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AliTTS 阿里云语音合成
|
||||||
|
// 同一时间只能播放一个 TTS
|
||||||
type AliTTS struct {
|
type AliTTS struct {
|
||||||
config.AliyunConfig
|
config.AliyunConfig
|
||||||
ctx context.Context
|
|
||||||
tokenResult nls.TokenResult
|
tokenResult nls.TokenResult
|
||||||
|
mu sync.Mutex // 互斥锁,确保同时只播放一个
|
||||||
}
|
}
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
@@ -29,78 +31,85 @@ type result struct {
|
|||||||
|
|
||||||
var DefaultTTS = &AliTTS{}
|
var DefaultTTS = &AliTTS{}
|
||||||
|
|
||||||
// onTaskFailed 识别过程中的错误处理回调参数
|
// onTaskFailed TTS 合成失败回调
|
||||||
func (tts *AliTTS) onTaskFailed(text string, param interface{}) {
|
func (tts *AliTTS) onTaskFailed(text string, param interface{}) {
|
||||||
p, _ := param.(*result)
|
p, _ := param.(*result)
|
||||||
p.Error = fmt.Errorf("语音合成异常: %v", text)
|
p.Error = fmt.Errorf("语音合成异常: %v", text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// onSynthesisResult 语音合成数据回调参数
|
// onSynthesisResult TTS 合成数据回调
|
||||||
func (tts *AliTTS) onSynthesisResult(data []byte, param interface{}) {
|
func (tts *AliTTS) onSynthesisResult(data []byte, param interface{}) {
|
||||||
p, _ := param.(*result)
|
p, _ := param.(*result)
|
||||||
p.Data.Write(data)
|
p.Data.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tts *AliTTS) Sound(text string) {
|
// Sound 播放 TTS
|
||||||
|
// 如果已有 TTS 在播放,会等待当前播放完成后再播放新的
|
||||||
|
func (tts *AliTTS) Sound(ctx context.Context, text string) {
|
||||||
if text == "" {
|
if text == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
zap.S().Infof("开始播放TTS: %s", text)
|
|
||||||
buf, err := tts.Get(text)
|
|
||||||
if err == nil && buf != nil {
|
|
||||||
zap.S().Debugln("TTS合成成功,开始播放")
|
|
||||||
audio.PlayWav(tts.ctx, buf)
|
|
||||||
zap.S().Infof("TTS播放完成: %s", text)
|
|
||||||
} else {
|
|
||||||
zap.S().Errorln("AliTTS 请求异常: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SoundWithContext 使用指定的 context 播放 TTS,支持取消和超时
|
zap.S().Infof("[TTS] 开始播放: %s", text)
|
||||||
func (tts *AliTTS) SoundWithContext(ctx context.Context, text string) {
|
|
||||||
if text == "" {
|
buf, err := tts.Get(ctx, text)
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Errorw("[TTS] 合成失败", "text", text, "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
zap.S().Infof("开始播放TTS: %s", text)
|
|
||||||
buf, err := tts.Get(text)
|
size := buf.(*bytes.Buffer).Len()
|
||||||
if err == nil && buf != nil {
|
zap.S().Debugf("[TTS] 合成成功: %s (%d字节)", text, size)
|
||||||
zap.S().Debugln("TTS合成成功,开始播放")
|
|
||||||
|
// 获取锁,阻塞等待直到可以播放
|
||||||
|
zap.S().Debugf("[TTS] 等待播放锁: %s", text)
|
||||||
|
tts.mu.Lock()
|
||||||
|
defer tts.mu.Unlock()
|
||||||
|
|
||||||
audio.PlayWav(ctx, buf)
|
audio.PlayWav(ctx, buf)
|
||||||
zap.S().Infof("TTS播放完成: %s", text)
|
|
||||||
} else {
|
// 检查是否被取消
|
||||||
zap.S().Errorln("AliTTS 请求异常: ", err)
|
if ctx.Err() != nil {
|
||||||
|
zap.S().Debugf("[TTS] 播放被取消: %s", text)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zap.S().Infof("[TTS] 播放完成: %s", text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getToken 获取阿里云 TTS Token
|
||||||
func (tts *AliTTS) getToken() error {
|
func (tts *AliTTS) getToken() error {
|
||||||
|
// Token 未过期则复用
|
||||||
if tts.tokenResult.ExpireTime != 0 && time.Unix(tts.tokenResult.ExpireTime, 0).After(time.Now()) {
|
if tts.tokenResult.ExpireTime != 0 && time.Unix(tts.tokenResult.ExpireTime, 0).After(time.Now()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tts.tokenResult = nls.TokenResult{}
|
tts.tokenResult = nls.TokenResult{}
|
||||||
resultMessage, err := nls.GetToken("cn-shanghai", "nls-meta.cn-shanghai.aliyuncs.com", tts.AccessKeyID, tts.AccessKeySecret, "2019-02-28")
|
resultMessage, err := nls.GetToken("cn-shanghai", "nls-meta.cn-shanghai.aliyuncs.com", tts.AccessKeyID, tts.AccessKeySecret, "2019-02-28")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if resultMessage.ErrMsg != "" {
|
|
||||||
zap.S().Errorf("获取Token失败: %s", resultMessage.ErrMsg)
|
|
||||||
return errorsx.ThirdPartyErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resultMessage.ErrMsg != "" {
|
||||||
|
return fmt.Errorf("获取Token失败: %s", resultMessage.ErrMsg)
|
||||||
|
}
|
||||||
|
|
||||||
tts.tokenResult = resultMessage.TokenResult
|
tts.tokenResult = resultMessage.TokenResult
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tts *AliTTS) Get(text string) (io.Reader, error) {
|
// Get 合成语音文本(内部方法)
|
||||||
|
func (tts *AliTTS) Get(ctx context.Context, text string) (io.Reader, error) {
|
||||||
param := nls.DefaultSpeechSynthesisParam()
|
param := nls.DefaultSpeechSynthesisParam()
|
||||||
param.Volume = tts.Volume
|
param.Volume = tts.Volume
|
||||||
param.Voice = tts.Voice
|
param.Voice = tts.Voice
|
||||||
param.SpeechRate = tts.SpeechRate
|
param.SpeechRate = tts.SpeechRate
|
||||||
|
|
||||||
err := tts.getToken()
|
if err := tts.getToken(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
connectConfig := nls.NewConnectionConfigWithToken(nls.DEFAULT_URL, tts.AppKey, tts.tokenResult.Id)
|
connectConfig := nls.NewConnectionConfigWithToken(nls.DEFAULT_URL, tts.AppKey, tts.tokenResult.Id)
|
||||||
|
|
||||||
logger := nls.NewNlsLogger(leaf.DefaultWriter, "", log.LstdFlags|log.Ltime)
|
logger := nls.NewNlsLogger(leaf.DefaultWriter, "", log.LstdFlags|log.Ltime)
|
||||||
logger.SetLogSil(false)
|
logger.SetLogSil(false)
|
||||||
logger.SetDebug(true)
|
logger.SetDebug(true)
|
||||||
@@ -124,34 +133,29 @@ func (tts *AliTTS) Get(text string) (io.Reader, error) {
|
|||||||
return ttsData.Data, err
|
return ttsData.Data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待语音合成结束
|
// 等待合成完成
|
||||||
select {
|
select {
|
||||||
case done := <-ch:
|
case done := <-ch:
|
||||||
{
|
|
||||||
if !done {
|
if !done {
|
||||||
zap.S().Errorln("TTS合成失败: done=false")
|
return ttsData.Data, fmt.Errorf("TTS合成失败")
|
||||||
return ttsData.Data, errorsx.ThirdPartyErr
|
|
||||||
}
|
}
|
||||||
size := ttsData.Data.(*bytes.Buffer).Len()
|
size := ttsData.Data.(*bytes.Buffer).Len()
|
||||||
zap.S().Debugf("TTS合成成功,数据大小: %d bytes", size)
|
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
zap.S().Errorln("TTS合成数据为空")
|
return ttsData.Data, fmt.Errorf("TTS合成数据为空")
|
||||||
return ttsData.Data, errorsx.ThirdPartyErr
|
|
||||||
}
|
}
|
||||||
return ttsData.Data, nil
|
return ttsData.Data, nil
|
||||||
}
|
|
||||||
case <-time.After(time.Duration(tts.Timeout) * time.Second):
|
case <-time.After(time.Duration(tts.Timeout) * time.Second):
|
||||||
zap.S().Errorln("TTS合成超时")
|
return ttsData.Data, fmt.Errorf("TTS合成超时")
|
||||||
return ttsData.Data, errorsx.DriverTimeoutErr
|
|
||||||
case <-tts.ctx.Done():
|
case <-ctx.Done():
|
||||||
zap.S().Errorln("TTS合成被取消")
|
return ttsData.Data, fmt.Errorf("请求被取消")
|
||||||
return ttsData.Data, errorsx.DriverCancelErr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, config config.AliyunConfig) *AliTTS {
|
// New 创建 TTS 实例
|
||||||
|
func New(config config.AliyunConfig) *AliTTS {
|
||||||
return &AliTTS{
|
return &AliTTS{
|
||||||
ctx: ctx,
|
|
||||||
AliyunConfig: config,
|
AliyunConfig: config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user