Compare commits

..

4 Commits

Author SHA1 Message Date
Rice 354ef31933 fix:电表型号联动
2 months ago
Rice 6471e68928 fix:中间任务时间解析错误
2 months ago
Rice 70b8a2570e error 更换
2 months ago
Rice ce71603127 error 更换
2 months ago

@ -29,9 +29,10 @@
"baudRate": "9600"
},
"deviceInfo": {
"deviceId": "866749078669632",
"deviceId": "862809073336480",
"version": "1.0.2",
"meterAddr": "0x04"
"meterAddr": "0x04",
"meterFirm": "ADL400"
},
"MessageInterval": 15,
"Firefox": {

@ -10,12 +10,14 @@ import (
"tgk-touch/internal/module/adl400TtyApi"
m9zTtyApi "tgk-touch/internal/module/m9zTtyApi"
"tgk-touch/internal/module/m9zTtyPwd"
"tgk-touch/internal/module/meterFirm"
)
func Init() {
CfgInit()
ZapInit()
m9zTtyPwd.Init()
meterFirm.Init()
m9zTtyApi.Init()
adl400TtyApi.Init()
timer()

@ -1,16 +1,23 @@
package meterControl
import "tgk-touch/internal/library/meterControl/Adl200Impl"
import (
"log"
"tgk-touch/internal/library/meterControl/Adl200Impl"
)
import "tgk-touch/internal/library/meterControl/Adl400Impl"
type MeterFirm string
const (
ADL200 MeterFirm = "AEM-ADL200"
ADL400 MeterFirm = "AEM-ADL400"
ADL200 MeterFirm = "ADL200"
ADL400 MeterFirm = "ADL400"
)
var (
MeterFirms = map[string]MeterFirm{
"ADL200": ADL200,
"ADL400": ADL400,
}
meterControls = make(map[MeterFirm]IMeterControl)
readMeterControls = make(map[MeterFirm]IReadMeter)
writeMeterControls = make(map[MeterFirm]IWriteMeter)
@ -29,6 +36,10 @@ func init() {
}
func GetMeterControls(firm MeterFirm) IMeterControl {
log.Println("GetMeterControls", firm)
_, ok := meterControls[firm]
log.Println("GetMeterControls", ok)
log.Println("GetMeterControls", meterControls)
if v, ok := meterControls[firm]; ok {
return v
}

@ -99,6 +99,7 @@ type (
DeviceId string `json:"deviceId" mapstructure:"deviceId"`
Version string `json:"version" mapstructure:"version"`
MeterAddr string `json:"meterAddr" mapstructure:"meterAddr"`
MeterFirm string `json:"meterFirm" mapstructure:"meterFirm"`
}
Firefox struct {

@ -2,26 +2,36 @@
package adl400TtyApi
import (
"encoding/json"
"log"
"strings"
"github.com/gogf/gf/v2/util/gconv"
"github.com/towgo/towgo/towgo"
"strings"
"tgk-touch/internal/global"
"tgk-touch/internal/library/meterControl"
"tgk-touch/internal/model/config"
"tgk-touch/internal/module/meterFirm"
)
var mc meterControl.IMeterControl
var deviceInfo map[string]interface{}
var mc2 meterControl.IMeterControl
var deviceInfo config.DeviceInfo
func Init() {
marshal, _ := json.Marshal(g.Config().DeviceInfo)
json.Unmarshal(marshal, &deviceInfo)
mc = meterControl.GetMeterControls(meterControl.ADL400)
deviceInfo = g.Config().DeviceInfo
mc2 = meterFirm.Manager().GetMeterControl()
meterFirm.Manager().RegisterReloadCallback(Reload)
initReadFunc()
initWriteFunc()
}
func getMc() meterControl.IMeterControl {
log.Println("getMc==", mc2, meterFirm.Manager().Get())
if mc2 == nil {
mc2 = meterFirm.Manager().GetMeterControl()
}
return mc2
}
func Reload() {
mc2 = meterFirm.Manager().GetMeterControl()
}
func initReadFunc() {
towgo.SetFunc("/adl400/readPhaseData", readPhaseData)
@ -41,8 +51,6 @@ func initWriteFunc() {
towgo.SetFunc("/adl400/setMsgAddress", setMsgAddress)
}
func getMeterAddr(cuid string) byte {
// 去掉 "0x" 前缀,按 16 进制解析
return gconv.Byte(strings.TrimPrefix(deviceInfo["meterAddr"].(string), "0x"))
return gconv.Byte(strings.TrimPrefix(deviceInfo.MeterAddr, "0x"))
}

@ -21,7 +21,7 @@ func readPhaseData(rpc towgo.JsonRpcConnection) {
addr := getMeterAddr(p.CommUid)
rtuCommUid := p.CommUid
var mp deviceManagement.MeterPower
totalEnergy, aEnergy, bEnergy, cEnergy, err := mc.ReadEnergy(rtuCommUid, addr)
totalEnergy, aEnergy, bEnergy, cEnergy, err := getMc().ReadEnergy(rtuCommUid, addr)
if err != nil {
panic(err)
}
@ -30,7 +30,7 @@ func readPhaseData(rpc towgo.JsonRpcConnection) {
mp.BEnergy = math.Round(bEnergy*100) / 100
mp.CEnergy = math.Round(cEnergy*100) / 100
_, aVoltage, bVoltage, cVoltage, err := mc.ReadVoltage(rtuCommUid, addr)
_, aVoltage, bVoltage, cVoltage, err := getMc().ReadVoltage(rtuCommUid, addr)
if err != nil {
panic(err)
}
@ -38,7 +38,7 @@ func readPhaseData(rpc towgo.JsonRpcConnection) {
mp.BVoltage = math.Round(bVoltage*100) / 100
mp.CVoltage = math.Round(cVoltage*100) / 100
_, aElectricCurrent, bElectricCurrent, cElectricCurrent, err := mc.ReadElectricCurrent(rtuCommUid, addr)
_, aElectricCurrent, bElectricCurrent, cElectricCurrent, err := getMc().ReadElectricCurrent(rtuCommUid, addr)
if err != nil {
panic(err)
}
@ -46,7 +46,7 @@ func readPhaseData(rpc towgo.JsonRpcConnection) {
mp.BElectricCurrent = math.Round(bElectricCurrent*100) / 100
mp.CElectricCurrent = math.Round(cElectricCurrent*100) / 100
totalPower, aPower, bPower, cPower, err := mc.ReadPower(rtuCommUid, addr)
totalPower, aPower, bPower, cPower, err := getMc().ReadPower(rtuCommUid, addr)
if err != nil {
panic(err)
}
@ -54,7 +54,7 @@ func readPhaseData(rpc towgo.JsonRpcConnection) {
mp.APower = math.Round(aPower*100) / 100
mp.BPower = math.Round(bPower*100) / 100
mp.CPower = math.Round(cPower*100) / 100
tf, af, bf, cf, err := mc.ReadPowerFactor(rtuCommUid, addr)
tf, af, bf, cf, err := getMc().ReadPowerFactor(rtuCommUid, addr)
if err != nil {
panic(err)
}
@ -73,7 +73,7 @@ func getMsgAddress(rpc towgo.JsonRpcConnection) {
CommUid string `json:"comm_uid"`
}
rpc.ReadParams(&p)
addr, err := mc.ReadMsgAddr(p.CommUid, getMeterAddr(p.CommUid))
addr, err := getMc().ReadMsgAddr(p.CommUid, getMeterAddr(p.CommUid))
if err != nil {
panic(err)
}
@ -87,7 +87,7 @@ func getDailyFreezingTime(rpc towgo.JsonRpcConnection) {
}
rpc.ReadParams(&p)
time, err := mc.ReadDailyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
time, err := getMc().ReadDailyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
if err != nil {
panic(gerror.Wrap(err, "getDailyFreezingTime"))
}
@ -101,7 +101,7 @@ func geDeviceTime(rpc towgo.JsonRpcConnection) {
}
rpc.ReadParams(&p)
time, err := mc.ReadTime(p.CommUid, getMeterAddr(p.CommUid))
time, err := getMc().ReadTime(p.CommUid, getMeterAddr(p.CommUid))
if err != nil {
panic(gerror.Wrap(err, "geTime"))
}
@ -115,7 +115,7 @@ func getReadMonthlyFreezingTime(rpc towgo.JsonRpcConnection) {
}
rpc.ReadParams(&p)
day, hour, err := mc.ReadMonthlyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
day, hour, err := getMc().ReadMonthlyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
if err != nil {
panic(gerror.Wrap(err, "getReadMonthlyFreezingTime"))
}

@ -15,7 +15,7 @@ func setMsgAddress(rpc towgo.JsonRpcConnection) {
oldAddr := getMeterAddr(p.CommUid)
newAddr := gconv.Byte(strings.TrimPrefix(p.MsgAddr, "0x"))
err := mc.WriteMsgAddr(p.CommUid, oldAddr, newAddr)
err := getMc().WriteMsgAddr(p.CommUid, oldAddr, newAddr)
if err != nil {
panic(err)
}

@ -30,7 +30,7 @@ func ScanM9z() {
}
defer l.Unlock()
/** 挨个查询是否有报警*/
cuid := deviceInfo["deviceId"].(string)
cuid := g.Config().DeviceInfo.DeviceId
for i := 0; i < 10; i++ {
read, err := m9z.SubLoopParametersRead(cuid, uint(i))
if err != nil {

@ -1,18 +1,15 @@
package m9zApi
import (
"encoding/json"
"github.com/gogf/gf/v2/errors/gerror"
"tgk-touch/internal/module/meterFirm"
"github.com/towgo/towgo/towgo"
"tgk-touch/internal/global"
)
var deviceInfo map[string]interface{}
func Init() {
marshal, _ := json.Marshal(g.Config().DeviceInfo)
json.Unmarshal(marshal, &deviceInfo)
towgo.SetFunc("/m9z/fault/list", faultList)
towgo.SetFunc("/m9z/fault/batchExec", execFailByIds)
// 获取设备输出状态参数
@ -81,7 +78,8 @@ func Init() {
}
func getTouchDeviceId(rpc towgo.JsonRpcConnection) {
deviceInfo := g.Config().DeviceInfo
deviceInfo.MeterFirm = meterFirm.Manager().Get()
rpc.WriteResult(deviceInfo)
}
func faultDelete(rpc towgo.JsonRpcConnection) {

@ -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

@ -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,
})
}

@ -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)
}

Loading…
Cancel
Save