diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84efccb --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/logs + +*.mp3 \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go index 74d4d43..4093eec 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,7 +6,7 @@ package cmd import ( "game-driver/config" "game-driver/internal" - "game-driver/pkg/logger" + "log" "os" "github.com/spf13/cobra" @@ -56,11 +56,11 @@ func initConfig() { // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil { - logger.Infof("Using config file: %s", viper.ConfigFileUsed()) + log.Printf("Using config file: %s", viper.ConfigFileUsed()) } err := viper.Unmarshal(&config.C) if err != nil { - logger.Panicln("unmarshal config failed: ", err) + log.Panicln("unmarshal config failed: ", err) } } diff --git a/config/config.go b/config/config.go index c882576..c3097f8 100644 --- a/config/config.go +++ b/config/config.go @@ -1,13 +1,6 @@ package config -type config struct { - Location string - Point int - Relay string - Mqtt MqttConfig - Aliyun AliyunConfig - Game GameConfig -} +import "gopkg.in/natefinch/lumberjack.v2" type MqttConfig struct { Url string @@ -24,4 +17,19 @@ type GameConfig struct { MaxTimeout int } +type Logger struct { + File *lumberjack.Logger + Level string +} + +type config struct { + Location string + Point int + Relay string + Log Logger + Mqtt MqttConfig + Aliyun AliyunConfig + Game GameConfig +} + var C config diff --git a/go.mod b/go.mod index 808f94c..b9cb8f0 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,12 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 go.bug.st/serial v1.6.2 + go.uber.org/zap v1.27.0 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( - github.com/aliyun/alibaba-cloud-sdk-go v1.63.45 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.63.51 // indirect github.com/creack/goselect v0.1.2 // indirect github.com/ebitengine/oto/v3 v3.3.1 // indirect github.com/ebitengine/purego v0.8.1 // indirect @@ -38,13 +40,11 @@ require ( github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect - golang.org/x/net v0.30.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1fd83ed..7f61b5a 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1376/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ= -github.com/aliyun/alibaba-cloud-sdk-go v1.63.45 h1:H74VbmrHgZcb7MN9ud8panaIXtY1nLgHZRWjJv2gyKU= -github.com/aliyun/alibaba-cloud-sdk-go v1.63.45/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.51 h1:ezfQdoOrqK7xa0+t8uw7ih2TFA/dm/bTH+U0/0Y++7g= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.51/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/go.mod h1:4BDMUKpEaP/Ct79w0ozR0nbnEj49g1k3mrgX/IKG5I4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -137,8 +137,8 @@ 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-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-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= 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-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -147,18 +147,18 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= 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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -178,6 +178,8 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/common/device.go b/internal/common/device.go index 980c405..d6d606b 100644 --- a/internal/common/device.go +++ b/internal/common/device.go @@ -3,9 +3,9 @@ package common import ( "context" "fmt" - "game-driver/pkg/logger" "github.com/eclipse/paho.golang/autopaho" "github.com/eclipse/paho.golang/paho" + "go.uber.org/zap" "sync" "sync/atomic" ) @@ -30,14 +30,14 @@ func (d *Device) Lock() { defer d.OnChange() d.mu.Lock() d.status.Store(1) - logger.Infoln("设备上锁") + zap.S().Infoln("设备上锁") } func (d *Device) Unlock() { defer d.OnChange() d.status.Store(0) d.mu.Unlock() - logger.Infoln("设备解锁") + zap.S().Infoln("设备解锁") } func (d *Device) Status() int { diff --git a/internal/middleware/bgm.go b/internal/middleware/bgm.go index a0caea2..785d238 100644 --- a/internal/middleware/bgm.go +++ b/internal/middleware/bgm.go @@ -4,9 +4,9 @@ import ( "game-driver/internal/schema" "game-driver/leaf" "game-driver/pkg/audio" - "game-driver/pkg/logger" "game-driver/pkg/utils" "github.com/gopxl/beep/v2/speaker" + "go.uber.org/zap" "sync" ) @@ -17,10 +17,10 @@ func PlayBgm() leaf.HandlerFunc { bgm, err := utils.LinkAudio(pm.BGM) if err != nil { - logger.Errorln("背景音乐数据解析异常:", err) + zap.S().Errorln("背景音乐数据解析异常:", err) } if bgm != nil { - logger.Infoln("背景音乐解析成功") + zap.S().Infoln("背景音乐解析成功") // 等待组 var wait sync.WaitGroup defer wait.Wait() @@ -34,13 +34,13 @@ func PlayBgm() leaf.HandlerFunc { go func() { defer wait.Done() - logger.Infoln("开始播放背景音乐") - defer logger.Infoln("结束背景音乐播放") + zap.S().Infoln("开始播放背景音乐") + defer zap.S().Infoln("结束背景音乐播放") ctrl, closer, e := audio.PlayBgmMP3(bgm) defer closer() if e != nil { - logger.Errorln("播放背景音乐异常:", e) + zap.S().Errorln("播放背景音乐异常:", e) return } @@ -55,7 +55,7 @@ func PlayBgm() leaf.HandlerFunc { } }() } else { - logger.Errorln("背景音乐解析为空") + zap.S().Errorln("背景音乐解析为空") } c.Next() diff --git a/internal/middleware/json.go b/internal/middleware/json.go index 978097d..1a7ffca 100644 --- a/internal/middleware/json.go +++ b/internal/middleware/json.go @@ -4,7 +4,7 @@ import ( "encoding/json" "game-driver/internal/schema" "game-driver/leaf" - "game-driver/pkg/logger" + "go.uber.org/zap" ) type JSONKey string @@ -17,7 +17,7 @@ func PayloadJSON[T schema.JsonModel]() leaf.HandlerFunc { pm := new(T) err := json.Unmarshal(c.Payload, pm) if err != nil { - logger.Panicln("报文解析错误", err) + zap.S().Panicln("报文解析错误", err) } leaf.WithValue[*T](c, PayloadJSONKey, pm) c.Next() diff --git a/internal/middleware/log.go b/internal/middleware/log.go index 18f1c8e..7c92847 100644 --- a/internal/middleware/log.go +++ b/internal/middleware/log.go @@ -2,13 +2,13 @@ package middleware import ( "game-driver/leaf" - "game-driver/pkg/logger" + "go.uber.org/zap" ) func RunLog() leaf.HandlerFunc { return func(c *leaf.Context) { - logger.Infof("收到消息, topic: %s, payload: %s", c.Topic, c.Payload) - defer logger.Infof("处理结束") + zap.S().Infof("收到消息, topic: %s, payload: %s", c.Topic, c.Payload) + defer zap.S().Infof("处理结束") c.Next() } diff --git a/internal/middleware/relay.go b/internal/middleware/relay.go index ed56aa8..ffee498 100644 --- a/internal/middleware/relay.go +++ b/internal/middleware/relay.go @@ -3,8 +3,8 @@ package middleware import ( "game-driver/internal/schema" "game-driver/leaf" - "game-driver/pkg/logger" "game-driver/pkg/relay" + "go.uber.org/zap" ) // RelayMaster 继电器中间件 @@ -15,10 +15,10 @@ func RelayMaster(r *relay.Device) leaf.HandlerFunc { r.On(1) defer r.Off(1) - logger.Infoln("开启电源") - defer logger.Infoln("关闭电源") + zap.S().Infoln("开启电源") + defer zap.S().Infoln("关闭电源") } else { - logger.Infoln("继电器未开启/不需要电源控制") + zap.S().Infoln("继电器未开启/不需要电源控制") } c.Next() } diff --git a/internal/middleware/stop.go b/internal/middleware/stop.go index f9b1198..c2b37f5 100644 --- a/internal/middleware/stop.go +++ b/internal/middleware/stop.go @@ -3,7 +3,7 @@ package middleware import ( "game-driver/internal/common" "game-driver/leaf" - "game-driver/pkg/logger" + "go.uber.org/zap" ) // EmergencyStop 紧急停止中间件 @@ -17,15 +17,15 @@ func EmergencyStop(stopper common.Stopper) leaf.HandlerFunc { // 发送结束信号 defer close(a) - logger.Infoln("监听停止信号") + zap.S().Infoln("监听停止信号") go func() { - defer logger.Infoln("结束停止信号监听") + defer zap.S().Infoln("结束停止信号监听") select { case <-a: case <-stopper.Done(): { - logger.Infoln("停止信号触发") + zap.S().Infoln("停止信号触发") cancel() leaf.WithValue[leaf.EndType](c, leaf.EndKey, leaf.EndStop) } diff --git a/internal/middleware/ticker.go b/internal/middleware/ticker.go index aca8b87..3fbbe97 100644 --- a/internal/middleware/ticker.go +++ b/internal/middleware/ticker.go @@ -3,8 +3,8 @@ package middleware import ( "game-driver/internal/schema" "game-driver/leaf" - "game-driver/pkg/logger" "game-driver/pkg/tts" + "go.uber.org/zap" "sync" "time" ) @@ -40,8 +40,8 @@ func TickerAction() leaf.HandlerFunc { ticker := time.NewTicker(time.Second) defer ticker.Stop() - logger.Infoln("开始 Ticker 计时") - defer logger.Infoln("结束 Ticker 计时") + zap.S().Infoln("开始 Ticker 计时") + defer zap.S().Infoln("结束 Ticker 计时") for over := false; !over; { select { diff --git a/internal/middleware/timer.go b/internal/middleware/timer.go index 5360cd9..bdb56a0 100644 --- a/internal/middleware/timer.go +++ b/internal/middleware/timer.go @@ -3,7 +3,7 @@ package middleware import ( "game-driver/internal/schema" "game-driver/leaf" - "game-driver/pkg/logger" + "go.uber.org/zap" "sync" "time" ) @@ -36,15 +36,15 @@ func TimeoutOver(maxTimeout int) leaf.HandlerFunc { go func() { defer wait.Done() - logger.Infoln("超时 Timer 监控开始") - defer logger.Infoln("超时 Timer 监控结束") + zap.S().Infoln("超时 Timer 监控开始") + defer zap.S().Infoln("超时 Timer 监控结束") // 结束标志 select { case <-a: case <-timer.C: // 定时器结束 { - logger.Infoln("超时 Timer 触发") + zap.S().Infoln("超时 Timer 触发") cancel() leaf.WithValue[leaf.EndType](c, leaf.EndKey, leaf.EndTimer) } diff --git a/internal/middleware/unique.go b/internal/middleware/unique.go index 8f9af5b..d1fcb9a 100644 --- a/internal/middleware/unique.go +++ b/internal/middleware/unique.go @@ -3,7 +3,7 @@ package middleware import ( "game-driver/internal/common" "game-driver/leaf" - "game-driver/pkg/logger" + "go.uber.org/zap" "sync" ) @@ -12,15 +12,15 @@ func Unique(stopper common.Stopper) leaf.HandlerFunc { var lock sync.Mutex return func(c *leaf.Context) { if !lock.TryLock() { - logger.Infoln("尝试加锁失败,执行停止任务") + zap.S().Infoln("尝试加锁失败,执行停止任务") stopper.Stop() lock.Lock() } - logger.Infoln("加锁完成") + zap.S().Infoln("加锁完成") defer func() { lock.Unlock() - logger.Infoln("解锁完成") + zap.S().Infoln("解锁完成") }() c.Next() diff --git a/internal/routes/command.go b/internal/routes/command.go index 221b140..0ff9cce 100644 --- a/internal/routes/command.go +++ b/internal/routes/command.go @@ -3,7 +3,7 @@ package routes import ( "game-driver/internal/common" "game-driver/leaf" - "game-driver/pkg/logger" + "go.uber.org/zap" ) func Command(d *common.Device) leaf.HandlerFunc { @@ -17,7 +17,7 @@ func Command(d *common.Device) leaf.HandlerFunc { case "status": d.PublishStatus() default: - logger.Infof("接收到无效指令: %s\n", cmd) + zap.S().Infof("接收到无效指令: %s\n", cmd) } } } diff --git a/internal/routes/play/only_video.go b/internal/routes/play/only_video.go index 0d9ca5a..94d1d71 100644 --- a/internal/routes/play/only_video.go +++ b/internal/routes/play/only_video.go @@ -4,9 +4,9 @@ import ( "game-driver/internal/middleware" "game-driver/internal/schema" "game-driver/leaf" - "game-driver/pkg/logger" "game-driver/pkg/utils" "game-driver/pkg/video" + "go.uber.org/zap" ) func OnlyVideo(c *leaf.Context) { @@ -18,7 +18,7 @@ func OnlyVideo(c *leaf.Context) { if url, ok := payload.Game["video"]; ok { local, err := utils.LinkVideo(url.(string)) if err != nil { - logger.Errorln("视频文件获取异常: ", err) + zap.S().Errorln("视频文件获取异常: ", err) return } _ = video.Play(c, local) diff --git a/internal/routes/wait.go b/internal/routes/wait.go index 3fdd11b..2646a14 100644 --- a/internal/routes/wait.go +++ b/internal/routes/wait.go @@ -5,12 +5,12 @@ import ( "game-driver/internal/schema" "game-driver/leaf" "game-driver/pkg/audio" - "game-driver/pkg/logger" "game-driver/pkg/relay" "game-driver/pkg/tts" "game-driver/pkg/utils" "game-driver/pkg/video" "github.com/gopxl/beep/v2/speaker" + "go.uber.org/zap" "sync" "time" ) @@ -34,7 +34,7 @@ func WaitAction(c *leaf.Context) { payload := leaf.Value[*schema.WaitModel](c, middleware.PayloadJSONKey) if payload.Start != 0 && payload.End != 0 && time.Unix(payload.Start, 0).After(time.Unix(payload.End, 0)) { - logger.Infoln("开始时间大于结束时间") + zap.S().Infoln("开始时间大于结束时间") return } @@ -81,7 +81,7 @@ func WaitAction(c *leaf.Context) { }() case schema.WaitWeb: default: - logger.Infof("不支持的类型: %d\n", item.Type) + zap.S().Infof("不支持的类型: %d\n", item.Type) } } } @@ -89,7 +89,7 @@ func WaitAction(c *leaf.Context) { func audioAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel) { if item.Start != 0 && time.Unix(item.Start, 0).Before(time.Unix(root.Start, 0)) { - logger.Infoln("开始时间小于根任务开始时间") + zap.S().Infoln("开始时间小于根任务开始时间") return } @@ -100,7 +100,7 @@ func audioAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod data, err := utils.LinkAudio(item.Data) if err != nil { - logger.Errorln("音频数据获取异常: ", err) + zap.S().Errorln("音频数据获取异常: ", err) return } @@ -108,13 +108,13 @@ func audioAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod case <-c.Done(): case <-timerAction(item.Start): { - logger.Infoln("播放待机音乐") - defer logger.Infoln("结束待机音乐") + zap.S().Infoln("播放待机音乐") + defer zap.S().Infoln("结束待机音乐") ctrl, closer, e := audio.PlayBgmMP3(data) defer closer() if e != nil { - logger.Errorln("播放待机音乐异常", e) + zap.S().Errorln("播放待机音乐异常", e) return } @@ -132,7 +132,7 @@ func audioAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod func ttsAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel) { if item.Start != 0 && time.Unix(item.Start, 0).Before(time.Unix(root.Start, 0)) { - logger.Infoln("开始时间小于根任务开始时间") + zap.S().Infoln("开始时间小于根任务开始时间") return } @@ -143,7 +143,7 @@ func ttsAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel reader, err := tts.DefaultTTS.Get(item.Data) if err != nil { - logger.Errorln("语音合成异常: ", err) + zap.S().Errorln("语音合成异常: ", err) return } @@ -151,8 +151,8 @@ func ttsAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel case <-c.Done(): case <-timerAction(item.Start): { - logger.Infoln("循环播放待机 TTS 语音") - defer logger.Infoln("结束待机 TTS 语音") + zap.S().Infoln("循环播放待机 TTS 语音") + defer zap.S().Infoln("结束待机 TTS 语音") for { audio.PlayWav(c, reader) @@ -168,7 +168,7 @@ func ttsAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel func relayAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel) { if item.Start != 0 && time.Unix(item.Start, 0).Before(time.Unix(root.Start, 0)) { - logger.Infoln("开始时间小于根任务开始时间") + zap.S().Infoln("开始时间小于根任务开始时间") return } @@ -179,7 +179,7 @@ func relayAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod device, err := relay.New(item.Data, nil) if err != nil { - logger.Errorln("继电器初始化异常: ", err) + zap.S().Errorln("继电器初始化异常: ", err) return } defer device.Close() @@ -188,8 +188,8 @@ func relayAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod case <-c.Done(): case <-timerAction(item.Start): { - logger.Infoln("待机继电器供电") - defer logger.Infoln("待机继电器断电") + zap.S().Infoln("待机继电器供电") + defer zap.S().Infoln("待机继电器断电") device.On(1) <-c.Done() @@ -200,7 +200,7 @@ func relayAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod func videoAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeModel) { if item.Start != 0 && time.Unix(item.Start, 0).Before(time.Unix(root.Start, 0)) { - logger.Infoln("开始时间小于根任务开始时间") + zap.S().Infoln("开始时间小于根任务开始时间") return } @@ -211,7 +211,7 @@ func videoAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod local, err := utils.LinkVideo(item.Data) if err != nil { - logger.Errorln("视频文件获取异常: ", err) + zap.S().Errorln("视频文件获取异常: ", err) return } @@ -219,8 +219,8 @@ func videoAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod case <-c.Done(): case <-timerAction(item.Start): { - logger.Infoln("循环播放待机视频") - defer logger.Infoln("结束待机视频") + zap.S().Infoln("循环播放待机视频") + defer zap.S().Infoln("结束待机视频") utils.BlankOpen() defer utils.BlankClose() @@ -228,7 +228,7 @@ func videoAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod for { err := video.Play(c, local) if err != nil { - logger.Infof("视频播放异常: %s", err) + zap.S().Infof("视频播放异常: %s", err) return } select { diff --git a/internal/server.go b/internal/server.go index 28f7f03..0443ee6 100644 --- a/internal/server.go +++ b/internal/server.go @@ -9,7 +9,7 @@ import ( "game-driver/internal/routes" "game-driver/internal/schema" "game-driver/leaf" - "game-driver/pkg/logger" + "game-driver/logger" "game-driver/pkg/tts" "game-driver/pkg/utils" "github.com/eclipse/paho.golang/autopaho" @@ -25,12 +25,12 @@ import ( func buildMqtt(c config.MqttConfig, r *leaf.Engine, subTopics ...string) autopaho.ClientConfig { u, err := url.Parse(c.Url) if err != nil { - logger.Panicln("mqtt url parse error: ", err) + zap.S().Panicln("mqtt url parse error: ", err) } subscriptions := make([]paho.SubscribeOptions, 0) for _, topic := range subTopics { - logger.Infoln("订阅主题: ", topic) + zap.S().Infoln("订阅主题: ", topic) subscriptions = append(subscriptions, paho.SubscribeOptions{Topic: topic, QoS: 0}) } @@ -40,17 +40,17 @@ func buildMqtt(c config.MqttConfig, r *leaf.Engine, subTopics ...string) autopah CleanStartOnInitialConnection: false, SessionExpiryInterval: 60, OnConnectionUp: func(cm *autopaho.ConnectionManager, _ *paho.Connack) { - logger.Infoln("MQTT 连接成功") + zap.S().Infoln("MQTT 连接成功") if _, err := cm.Subscribe(context.Background(), &paho.Subscribe{ Subscriptions: subscriptions, }); err != nil { - logger.Errorf("failed to subscribe (%s). This is likely to mean no messages will be received.", err) + zap.S().Errorf("failed to subscribe (%s). This is likely to mean no messages will be received.", err) return } - logger.Infoln("订阅完成") + zap.S().Infoln("订阅完成") }, OnConnectError: func(err error) { - logger.Infof("MQTT 连接异常: %s\n", err) + zap.S().Infof("MQTT 连接异常: %s\n", err) }, ClientConfig: paho.ClientConfig{ ClientID: "TestSubscriber", @@ -60,12 +60,12 @@ func buildMqtt(c config.MqttConfig, r *leaf.Engine, subTopics ...string) autopah return true, nil }, }, - OnClientError: func(err error) { logger.Errorf("client error: %s\n", err) }, + OnClientError: func(err error) { zap.S().Errorf("client error: %s\n", err) }, OnServerDisconnect: func(d *paho.Disconnect) { if d.Properties != nil { - logger.Warnf("server requested disconnect: %s\n", d.Properties.ReasonString) + zap.S().Warnf("server requested disconnect: %s\n", d.Properties.ReasonString) } else { - logger.Warnf("server requested disconnect; reason code: %d\n", d.ReasonCode) + zap.S().Warnf("server requested disconnect; reason code: %d\n", d.ReasonCode) } }, }, @@ -75,6 +75,10 @@ func buildMqtt(c config.MqttConfig, r *leaf.Engine, subTopics ...string) autopah } func Run() { + logger.InitLogger() + // 应用退出时刷新所有缓冲日志 + defer logger.Sync() + topicPrefix := fmt.Sprintf("server/%s/%v/", config.C.Location, config.C.Point) publishTopic := fmt.Sprintf("device/%s/%v/status", config.C.Location, config.C.Point) @@ -82,14 +86,12 @@ func Run() { defer cancel() router := leaf.Default(ctx) - // 应用推出时刷新所有缓冲日志 - defer logger.DefaultLogger.Sync() - log, _ := zap.NewStdLogAt(logger.DefaultLogger.ZapLogger(), zap.DebugLevel) + log, _ := zap.NewStdLogAt(zap.L(), zap.DebugLevel) router.SetDebugLogger(log) router.DefaultHandler(func(c *leaf.Context) { - logger.Infof("未处理消息,topic: %s\n payload: %s\n", c.Topic, c.Payload) + zap.S().Infof("未处理消息,topic: %s\n payload: %s\n", c.Topic, c.Payload) }) // 构建 MQTT 连接 @@ -98,7 +100,7 @@ func Run() { // 连接 MQTT cm, err := autopaho.NewConnection(ctx, mqttBuild) if err != nil { - logger.Panicln("连接 MQTT 异常: ", err) + zap.S().Panicln("连接 MQTT 异常: ", err) } // 构建语音合成对象 @@ -106,10 +108,10 @@ func Run() { // 构建继电器对象 //r, err := relay.New(config.C.Relay, func(msg string) { - // logger.Infoln("串口返回: ", msg) + // zap.S().Infoln("串口返回: ", msg) //}) //if err != nil { - // logger.Panicln("串口连接异常: ", err) + // zap.S().Panicln("串口连接异常: ", err) //} //defer r.Close() @@ -154,13 +156,13 @@ func Run() { signal.Notify(sig, os.Interrupt, syscall.SIGTERM) <-sig - logger.Infoln("接收到关闭命令 - 正在关闭程序") + zap.S().Infoln("接收到关闭命令 - 正在关闭程序") ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if e := cm.Disconnect(ctx); e != nil { - logger.Errorln("断开连接异常", e) + zap.S().Errorln("断开连接异常", e) } - logger.Infoln("关闭完成") + zap.S().Infoln("关闭完成") } diff --git a/leaf/recovery.go b/leaf/recovery.go index 9d2b551..09e2138 100644 --- a/leaf/recovery.go +++ b/leaf/recovery.go @@ -5,7 +5,7 @@ package leaf import ( - "game-driver/pkg/logger" + "go.uber.org/zap" "io" ) @@ -35,7 +35,7 @@ func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc { return func(c *Context) { defer func() { if err := recover(); err != nil { - logger.Infoln("执行出错: ", err) + zap.S().Errorln("执行出错: ", err) handle(c, err) } }() diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..bbad675 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,38 @@ +package logger + +import ( + "game-driver/config" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "log" + "os" +) + +func InitLogger() { + // 解析日志级别 + level, err := zapcore.ParseLevel(config.C.Log.Level) + if err != nil { + log.Panicln("日志级别配置错误: ", err) + } + + // 默认开发模式 + nc := zap.NewDevelopmentEncoderConfig() + // console 格式输出 + cn := zapcore.NewConsoleEncoder(nc) + + // 多个输出 + mws := zapcore.NewMultiWriteSyncer(zapcore.AddSync(config.C.Log.File), zapcore.AddSync(os.Stdout)) + + // 核心配置 + core := zapcore.NewCore(cn, mws, level) + + // 构建 logger + logger := zap.New(core, zap.AddCaller()) + + // 替换全局 logger + zap.ReplaceGlobals(logger) +} + +func Sync() { + zap.L().Sync() +} diff --git a/main.go b/main.go index 73925d9..dbc6603 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,5 @@ /* Copyright © 2024 慕枫Go - */ package main diff --git a/pkg/audio/bgm.go b/pkg/audio/bgm.go index 07d438e..10c32ae 100644 --- a/pkg/audio/bgm.go +++ b/pkg/audio/bgm.go @@ -1,10 +1,10 @@ package audio import ( - "game-driver/pkg/logger" "github.com/gopxl/beep/v2" "github.com/gopxl/beep/v2/mp3" "github.com/gopxl/beep/v2/speaker" + "go.uber.org/zap" "io" ) @@ -16,7 +16,7 @@ func PlayBgmMP3(r io.ReadCloser, opts ...beep.LoopOption) (*beep.Ctrl, func() er loop2, err := beep.Loop2(streamer, opts...) if err != nil { - logger.Infoln("循环播放异常: ", err) + zap.S().Infoln("循环播放异常: ", err) return nil, streamer.Close, err } diff --git a/pkg/audio/play.go b/pkg/audio/play.go index af80bdc..62c3378 100644 --- a/pkg/audio/play.go +++ b/pkg/audio/play.go @@ -2,11 +2,11 @@ package audio import ( "context" - "game-driver/pkg/logger" "github.com/gopxl/beep/v2" "github.com/gopxl/beep/v2/mp3" "github.com/gopxl/beep/v2/speaker" "github.com/gopxl/beep/v2/wav" + "go.uber.org/zap" "io" "time" ) @@ -18,7 +18,7 @@ func init() { if err != nil { panic("扬声器初始化异常: " + err.Error()) } - logger.Infoln("扬声器初始化完成") + zap.S().Infoln("扬声器初始化完成") } func PlayWav(c context.Context, r io.Reader) { diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go deleted file mode 100644 index dc2cadd..0000000 --- a/pkg/logger/logger.go +++ /dev/null @@ -1,207 +0,0 @@ -package logger - -import ( - "go.uber.org/zap" -) - -type Logger struct { - zl *zap.Logger - zs zap.SugaredLogger -} - -func NewLogger() *Logger { - logger, _ := zap.NewDevelopment() - sugar := logger.WithOptions(zap.AddCallerSkip(1)).Sugar() - return &Logger{ - zl: logger, - zs: *sugar, - } -} - -// ZapLogger 返回 zap 原始的 zap.Logger -func (l *Logger) ZapLogger() *zap.Logger { - return l.zl -} - -// Sync 刷新所有缓冲的日志条目 -func (l *Logger) Sync() error { - return l.zs.Sync() -} - -var DefaultLogger = NewLogger() - -// Debug logs the provided arguments at [DebugLevel]. -// Spaces are added between arguments when neither is a string. -func Debug(args ...interface{}) { - DefaultLogger.zs.Log(zap.DebugLevel, args...) -} - -// Info logs the provided arguments at [InfoLevel]. -// Spaces are added between arguments when neither is a string. -func Info(args ...interface{}) { - DefaultLogger.zs.Log(zap.InfoLevel, args...) -} - -// Warn logs the provided arguments at [WarnLevel]. -// Spaces are added between arguments when neither is a string. -func Warn(args ...interface{}) { - DefaultLogger.zs.Log(zap.WarnLevel, args...) -} - -// Error logs the provided arguments at [ErrorLevel]. -// Spaces are added between arguments when neither is a string. -func Error(args ...interface{}) { - DefaultLogger.zs.Log(zap.ErrorLevel, args...) -} - -// DPanic logs the provided arguments at [DPanicLevel]. -// In development, the logger then panics. (See [DPanicLevel] for details.) -// Spaces are added between arguments when neither is a string. -func DPanic(args ...interface{}) { - DefaultLogger.zs.Log(zap.DPanicLevel, args...) -} - -// Panic constructs a message with the provided arguments and panics. -// Spaces are added between arguments when neither is a string. -func Panic(args ...interface{}) { - DefaultLogger.zs.Log(zap.PanicLevel, args...) -} - -// Fatal constructs a message with the provided arguments and calls os.Exit. -// Spaces are added between arguments when neither is a string. -func Fatal(args ...interface{}) { - DefaultLogger.zs.Log(zap.FatalLevel, args...) -} - -// Debugf formats the message according to the format specifier -// and logs it at [DebugLevel]. -func Debugf(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.DebugLevel, template, args...) -} - -// Infof formats the message according to the format specifier -// and logs it at [InfoLevel]. -func Infof(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.InfoLevel, template, args...) -} - -// Warnf formats the message according to the format specifier -// and logs it at [WarnLevel]. -func Warnf(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.WarnLevel, template, args...) -} - -// Errorf formats the message according to the format specifier -// and logs it at [ErrorLevel]. -func Errorf(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.ErrorLevel, template, args...) -} - -// DPanicf formats the message according to the format specifier -// and logs it at [DPanicLevel]. -// In development, the logger then panics. (See [DPanicLevel] for details.) -func DPanicf(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.DPanicLevel, template, args...) -} - -// Panicf formats the message according to the format specifier -// and panics. -func Panicf(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.PanicLevel, template, args...) -} - -// Fatalf formats the message according to the format specifier -// and calls os.Exit. -func Fatalf(template string, args ...interface{}) { - DefaultLogger.zs.Logf(zap.FatalLevel, template, args...) -} - -// Debugw logs a message with some additional context. The variadic key-value -// pairs are treated as they are in With. -// -// When debug-level logging is disabled, this is much faster than -// -// s.With(keysAndValues).Debug(msg) -func Debugw(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.DebugLevel, msg, keysAndValues...) -} - -// Infow logs a message with some additional context. The variadic key-value -// pairs are treated as they are in With. -func Infow(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.InfoLevel, msg, keysAndValues...) -} - -// Warnw logs a message with some additional context. The variadic key-value -// pairs are treated as they are in With. -func Warnw(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.WarnLevel, msg, keysAndValues...) -} - -// Errorw logs a message with some additional context. The variadic key-value -// pairs are treated as they are in With. -func Errorw(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.ErrorLevel, msg, keysAndValues...) -} - -// DPanicw logs a message with some additional context. In development, the -// logger then panics. (See DPanicLevel for details.) The variadic key-value -// pairs are treated as they are in With. -func DPanicw(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.DPanicLevel, msg, keysAndValues...) -} - -// Panicw logs a message with some additional context, then panics. The -// variadic key-value pairs are treated as they are in With. -func Panicw(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.PanicLevel, msg, keysAndValues...) -} - -// Fatalw logs a message with some additional context, then calls os.Exit. The -// variadic key-value pairs are treated as they are in With. -func Fatalw(msg string, keysAndValues ...interface{}) { - DefaultLogger.zs.Logw(zap.FatalLevel, msg, keysAndValues...) -} - -// Debugln logs a message at [DebugLevel]. -// Spaces are always added between arguments. -func Debugln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.DebugLevel, args...) -} - -// Infoln logs a message at [InfoLevel]. -// Spaces are always added between arguments. -func Infoln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.InfoLevel, args...) -} - -// Warnln logs a message at [WarnLevel]. -// Spaces are always added between arguments. -func Warnln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.WarnLevel, args...) -} - -// Errorln logs a message at [ErrorLevel]. -// Spaces are always added between arguments. -func Errorln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.ErrorLevel, args...) -} - -// DPanicln logs a message at [DPanicLevel]. -// In development, the logger then panics. (See [DPanicLevel] for details.) -// Spaces are always added between arguments. -func DPanicln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.DPanicLevel, args...) -} - -// Panicln logs a message at [PanicLevel] and panics. -// Spaces are always added between arguments. -func Panicln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.PanicLevel, args...) -} - -// Fatalln logs a message at [FatalLevel] and calls os.Exit. -// Spaces are always added between arguments. -func Fatalln(args ...interface{}) { - DefaultLogger.zs.Logln(zap.FatalLevel, args...) -} diff --git a/pkg/tts/aliyun.go b/pkg/tts/aliyun.go index 60c3dec..7a8c543 100644 --- a/pkg/tts/aliyun.go +++ b/pkg/tts/aliyun.go @@ -8,7 +8,7 @@ import ( "game-driver/leaf" "game-driver/pkg/audio" "game-driver/pkg/errorsx" - "game-driver/pkg/logger" + "go.uber.org/zap" "io" "log" "time" @@ -49,7 +49,7 @@ func (tts *AliTTS) Sound(text string) { if err == nil && buf != nil { audio.PlayWav(tts.ctx, buf) } else { - logger.Errorln("AliTTS 请求异常: ", err) + zap.S().Errorln("AliTTS 请求异常: ", err) } } diff --git a/pkg/utils/link_audio.go b/pkg/utils/link_audio.go index 371b7bf..0618318 100644 --- a/pkg/utils/link_audio.go +++ b/pkg/utils/link_audio.go @@ -3,7 +3,7 @@ package utils import ( "bytes" "fmt" - "game-driver/pkg/logger" + "go.uber.org/zap" "io" "net/http" "net/url" @@ -33,7 +33,7 @@ func open(u string) io.ReadCloser { p, _ := strings.CutPrefix(u, "file://") f, e := os.Open(p) if e != nil { - logger.Infof("音频文件 [%v] 打开错误: %v\n", u, e) + zap.S().Infof("音频文件 [%v] 打开错误: %v\n", u, e) return nil } return f @@ -42,7 +42,7 @@ func open(u string) io.ReadCloser { func get(u string) io.ReadCloser { resp, e := http.Get(u) if e != nil { - logger.Infof("音频文件 [%v] 下载失败: %v\n", u, e) + zap.S().Infof("音频文件 [%v] 下载失败: %v\n", u, e) return nil } return resp.Body diff --git a/pkg/video/paly.go b/pkg/video/paly.go index ff1fbc4..d03dd42 100644 --- a/pkg/video/paly.go +++ b/pkg/video/paly.go @@ -3,7 +3,7 @@ package video import ( "bufio" "context" - "game-driver/pkg/logger" + "go.uber.org/zap" "io" "os/exec" "sync" @@ -11,7 +11,7 @@ import ( func Play(ctx context.Context, file string) error { if file == "" { - logger.Infoln("video file is empty") + zap.S().Infoln("video file is empty") return nil } cmd := exec.CommandContext(ctx, "ffplay", "-autoexit", "-fs", file) @@ -40,7 +40,7 @@ func Play(ctx context.Context, file string) error { } break } - logger.Infoln(string(line)) + zap.S().Infoln(string(line)) } } }() diff --git a/todo.md b/todo.md index 9926258..142794d 100644 --- a/todo.md +++ b/todo.md @@ -10,7 +10,7 @@ ``` 驱动安装 ```bash - libdirectfb-dev + sudo apt install libdirectfb-dev ``` 3. 当前用户加入播放音频与视频的组中 ```bash