From 6471e68928f6b62d06c1d54975c24eb9e277d356 Mon Sep 17 00:00:00 2001 From: Rice <1840169763@qq.com> Date: Mon, 25 May 2026 16:57:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=B8=AD=E9=97=B4=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E8=A7=A3=E6=9E=90=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/m9zCtrlTty/config/config.json | 3 +- internal/module/m9zTtyApi/set.go | 10 +- internal/module/meterFirm/init.go | 164 +++++++++++++++++++++++++++++ utility/directory.go | 20 ++++ 4 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 internal/module/meterFirm/init.go diff --git a/apps/m9zCtrlTty/config/config.json b/apps/m9zCtrlTty/config/config.json index e154c04..43c6657 100644 --- a/apps/m9zCtrlTty/config/config.json +++ b/apps/m9zCtrlTty/config/config.json @@ -31,7 +31,8 @@ "deviceInfo": { "deviceId": "866749078669632", "version": "1.0.2", - "meterAddr": "0x04" + "meterAddr": "0x04", + "meterFirm": "ADL400" }, "MessageInterval": 15, "Firefox": { diff --git a/internal/module/m9zTtyApi/set.go b/internal/module/m9zTtyApi/set.go index 8265c43..013f582 100644 --- a/internal/module/m9zTtyApi/set.go +++ b/internal/module/m9zTtyApi/set.go @@ -2,10 +2,12 @@ package m9zApi import ( "fmt" + "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "strings" g "tgk-touch/internal/global" m9z "tgk-touch/internal/library/m9z" + "tgk-touch/utility" "time" "github.com/towgo/towgo/towgo" @@ -300,7 +302,7 @@ func setStartTask2(rpc towgo.JsonRpcConnection) { if p.CommUid == "" { panic(gerror.New("comm_uid is empty")) } - parse, err := time.Parse("2006-01-02 15:04:05", p.ExecTime) + parse, err := utility.ParseTime(p.ExecTime) if err != nil { panic(err) } @@ -327,7 +329,7 @@ func setStopTask2(rpc towgo.JsonRpcConnection) { m9z.ControlTask } rpc.ReadParams(&p) - parse, err := time.Parse("2006-01-02 15:04:05", p.ExecTime) + parse, err := utility.ParseTime(p.ExecTime) if err != nil { panic(err) } @@ -368,9 +370,9 @@ func setMiddleTask2(rpc towgo.JsonRpcConnection) { middleTask := m9z.MiddleControlTask{} middleTask.ControlTaskList = make([]m9z.ControlTask, len(p.ControlTaskList)) for i, controlTask := range p.ControlTaskList { - parse, err := time.Parse("2006-01-02 15:04:05", controlTask.ExecTime) + parse, err := utility.ParseTime(controlTask.ExecTime) if err != nil { - panic(err) + panic(gerror.NewCodef(gcode.CodeInvalidParameter, " %s parse control task time error, %s", controlTask.ExecTime, err)) } controlTask.ControlTask.ExecTime = parse middleTask.ControlTaskList[i] = controlTask.ControlTask diff --git a/internal/module/meterFirm/init.go b/internal/module/meterFirm/init.go new file mode 100644 index 0000000..b0053d5 --- /dev/null +++ b/internal/module/meterFirm/init.go @@ -0,0 +1,164 @@ +package meterFirm + +import ( + "encoding/json" + "log" + "os" + "path/filepath" + "sync" + + g "tgk-touch/internal/global" + "tgk-touch/internal/library/meterControl" + + "github.com/towgo/towgo/lib/system" + "github.com/towgo/towgo/towgo" +) + +type MeterFirmManager struct { + mu sync.RWMutex + meterFirm string + onReload []func() +} + +type MeterFirmData struct { + MeterFirm string `json:"meter_firm"` +} + +var ( + manager *MeterFirmManager = &MeterFirmManager{} +) + +func Manager() *MeterFirmManager { + return manager +} + +func getMeterFirmFilePath() string { + return filepath.Join(system.GetPathOfProgram(), "data", "meterFirm.json") +} + +func (m *MeterFirmManager) Get() string { + m.mu.RLock() + defer m.mu.RUnlock() + return m.meterFirm +} + +func (m *MeterFirmManager) Set(firm string) error { + m.mu.Lock() + m.meterFirm = firm + if err := m.saveToFile(); err != nil { + m.mu.Unlock() + return err + } + + cbs := m.onReload + m.mu.Unlock() + + for _, cb := range cbs { + cb() + } + return nil +} + +func (m *MeterFirmManager) RegisterReloadCallback(cb func()) { + m.mu.Lock() + defer m.mu.Unlock() + m.onReload = append(m.onReload, cb) +} + +func (m *MeterFirmManager) saveToFile() error { + filePath := getMeterFirmFilePath() + dir := filepath.Dir(filePath) + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + + data := MeterFirmData{ + MeterFirm: m.meterFirm, + } + + jsonData, err := json.Marshal(data) + if err != nil { + return err + } + + return os.WriteFile(filePath, jsonData, 0600) +} + +func (m *MeterFirmManager) loadFromFile() error { + m.mu.Lock() + defer m.mu.Unlock() + + filePath := getMeterFirmFilePath() + jsonData, err := os.ReadFile(filePath) + if err != nil { + if os.IsNotExist(err) { + m.meterFirm = g.Config().DeviceInfo.MeterFirm + return m.saveToFile() + } + return err + } + + var data MeterFirmData + if err := json.Unmarshal(jsonData, &data); err != nil { + return err + } + + if data.MeterFirm == "" { + data.MeterFirm = g.Config().DeviceInfo.MeterFirm + } + + m.meterFirm = data.MeterFirm + return nil +} + +func (m *MeterFirmManager) GetMeterControl() meterControl.IMeterControl { + return meterControl.GetMeterControls(meterControl.MeterFirm(m.Get())) +} + +func Init() { + + if err := manager.loadFromFile(); err != nil { + g.GVA_LOG.Sugar().Warnf("load meterFirm data failed: %v, using default", err) + manager.meterFirm = g.Config().DeviceInfo.MeterFirm + log.Println("===========", g.Config().DeviceInfo.MeterFirm) + err = manager.saveToFile() + if err != nil { + panic(err) + } + } + + towgo.SetFunc("/m9z/meter/getMeterFirm", getMeterFirm) + towgo.SetFunc("/m9z/meter/setMeterFirm", setMeterFirm) +} + +func getMeterFirm(rpcConn towgo.JsonRpcConnection) { + rpcConn.WriteResult(map[string]interface{}{ + "meter_firm": manager.Get(), + }) +} + +type SetMeterFirmReq struct { + MeterFirm string `json:"meter_firm"` +} + +func setMeterFirm(rpcConn towgo.JsonRpcConnection) { + var req SetMeterFirmReq + rpcConn.ReadParams(&req) + if req.MeterFirm == "" { + rpcConn.WriteError(400, "meter_firm is required") + return + } + _, ok := meterControl.MeterFirms[req.MeterFirm] + if !ok { + rpcConn.WriteError(400, "invalid meter_firm, available: ADL400, DDSD1352, DTS1352") + return + } + if err := manager.Set(req.MeterFirm); err != nil { + rpcConn.WriteError(500, "save meter_firm failed: "+err.Error()) + return + } + rpcConn.WriteResult(map[string]interface{}{ + "success": true, + "meter_firm": req.MeterFirm, + }) +} diff --git a/utility/directory.go b/utility/directory.go index bc7e873..15b98d9 100644 --- a/utility/directory.go +++ b/utility/directory.go @@ -1,6 +1,7 @@ package utility import ( + "fmt" "github.com/gogf/gf/v2/errors/gerror" "io" "os" @@ -8,6 +9,7 @@ import ( "reflect" "strings" "tgk-touch/internal/global" + "time" "go.uber.org/zap" ) @@ -191,3 +193,21 @@ func FileExist(path string) bool { } return !os.IsNotExist(err) } + +// 解析时间:自动支持 2026-05-25T19:00:00+08:00 和 2026-05-25 19:00:00 +func ParseTime(str string) (time.Time, error) { + // 定义支持的格式 + layouts := []string{ + time.RFC3339, // 2026-05-25T19:00:00+08:00 + "2006-01-02 15:04:05", // 2026-05-25 19:00:00 + } + + for _, layout := range layouts { + t, err := time.ParseInLocation(layout, str, time.Local) + if err == nil { + return t, nil + } + } + + return time.Time{}, fmt.Errorf("无法解析时间: %s", str) +}