Ver código fonte

文件内容bug修改

xu 10 meses atrás
pai
commit
f66b14b8fe
12 arquivos alterados com 643 adições e 126 exclusões
  1. 10 0
      api/device.go
  2. 4 0
      go.mod
  3. 9 0
      go.sum
  4. 23 26
      initialize/myData.go
  5. 56 0
      logger/initLog.go
  6. 10 0
      main.go
  7. 22 13
      modbus/operate.go
  8. 8 39
      service/cron.go
  9. 9 11
      service/device.go
  10. 426 0
      static/data-fb.json
  11. 1 1
      static/data.json
  12. 65 36
      utils/myTool.go

+ 10 - 0
api/device.go

@@ -3,6 +3,7 @@ package api
 import (
 	"github.com/gin-gonic/gin"
 	"server/dao"
+	"server/logger"
 	"server/model"
 	"server/service"
 	"server/utils"
@@ -11,6 +12,7 @@ import (
 func LoadData(c *gin.Context) {
 	data, err := utils.LoadData()
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -21,11 +23,13 @@ func SaveDevice(c *gin.Context) {
 	var regions []dao.Region
 	err := c.ShouldBindJSON(&regions)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
 	err = service.SaveData(regions)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -37,11 +41,13 @@ func DeviceLoopSwitch(c *gin.Context) {
 	var deviceLoop dao.DeviceLoop
 	err := c.ShouldBindJSON(&deviceLoop)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
 	err = service.DeviceLoopSwitch(deviceLoop)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -58,6 +64,7 @@ func DeviceSwitch(c *gin.Context) {
 	}
 	err = service.DeviceSwitch(req)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -74,6 +81,7 @@ func BatchDeviceSwitch(c *gin.Context) {
 	}
 	err = service.DeviceBatchSwitch(req)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -92,6 +100,7 @@ func GetOnlineDevice(c *gin.Context) {
 func GetSunDevices(c *gin.Context) {
 	devices, err := service.GetSunDevices()
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -107,6 +116,7 @@ func UpdateRegisterAddress(c *gin.Context) {
 	}
 	err = service.UpdateRegisterAddress(id)
 	if err != nil {
+		logger.Get().Error(err.Error())
 		model.FailWithMessage(err.Error(), c)
 		return
 	}

+ 4 - 0
go.mod

@@ -23,10 +23,14 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.8 // indirect
 	github.com/leodido/go-urn v1.4.0 // indirect
+	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
+	github.com/lestrrat-go/strftime v1.1.0 // indirect
 	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/pelletier/go-toml/v2 v2.2.3 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/ugorji/go/codec v1.2.12 // indirect
 	golang.org/x/arch v0.11.0 // indirect

+ 9 - 0
go.sum

@@ -41,6 +41,10 @@ github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY
 github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
 github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
+github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
+github.com/lestrrat-go/strftime v1.1.0 h1:gMESpZy44/4pXLO/m+sL0yBd1W6LjgjrrD4a68Gapyg=
+github.com/lestrrat-go/strftime v1.1.0/go.mod h1:uzeIB52CeUJenCo1syghlugshMysrqUT51HlxphXVeI=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -50,10 +54,14 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
 github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
 github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -74,6 +82,7 @@ golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
 golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
 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/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=

+ 23 - 26
initialize/myData.go

@@ -2,13 +2,13 @@ package initialize
 
 import (
 	"encoding/hex"
-	"fmt"
 	"log"
 	"net"
 	"os"
 	"runtime"
 	"runtime/debug"
 	"server/dao"
+	"server/logger"
 	"server/modbus"
 	"server/model"
 	"server/service"
@@ -39,26 +39,26 @@ func GetHandler() *ModbusHandler {
 func InitInductanceTCP() {
 	lis, err := net.Listen("tcp", ":60001")
 	if err != nil {
-		fmt.Println(err)
+		logger.Get().Println(err)
 	} else {
-		fmt.Println(lis)
+		logger.Get().Println(lis)
 		model.InductanceTCP = lis
-		fmt.Println("inductanceTCP启动成功")
+		logger.Get().Println("inductanceTCP启动成功")
 	}
 	go StartInductanceTCP()
 }
 
 func StartInductanceTCP() {
-	fmt.Println("进入StartInductanceTCP")
+	logger.Get().Println("进入StartInductanceTCP")
 	handler := GetHandler()
 	for {
-		log.Println("进入InductanceTCP循环")
+		logger.Get().Println("进入InductanceTCP循环")
 		conn, err := model.InductanceTCP.Accept()
 		if err != nil {
 			log.Println(err)
 		}
 		remoteAddr := conn.RemoteAddr().String()
-		log.Printf("lis Accept conn = %s\n", remoteAddr)
+		logger.Get().Printf("lis Accept conn = %s\n", remoteAddr)
 
 		model.Mutex.Lock()
 		if _, exists := model.ConnectionMap[remoteAddr]; exists {
@@ -67,7 +67,6 @@ func StartInductanceTCP() {
 			model.Mutex.Unlock()
 			continue
 		}
-		fmt.Println(conn)
 		deviceId, err := GetDeviceId(conn)
 		if err != nil {
 			log.Println("Error getting device ID:", err)
@@ -97,18 +96,14 @@ func (o *ModbusHandler) ReadAndHandle(conn net.Conn, deviceId string) {
 	for {
 		buffer := make([]byte, 1024)
 		n, err := conn.Read(buffer)
-		//if err != nil {
-		//	log.Println("Error reading from connection:", err)
-		//	return
-		//}
 		if err != nil {
 			if isConnReset(err) {
-				fmt.Println("连接被远程主机强制关闭")
+				logger.Get().Error("连接被远程主机强制关闭")
 			} else if os.IsTimeout(err) {
-				fmt.Println("读取操作超时")
+				logger.Get().Error("读取操作超时")
 			} else {
 				// 处理其他类型的错误
-				fmt.Printf("读取错误: %s\n", err)
+				logger.Get().Errorf("读取错误: %s\n", err)
 			}
 			return
 		}
@@ -120,7 +115,7 @@ func (o *ModbusHandler) ReadAndHandle(conn net.Conn, deviceId string) {
 		if ok {
 			continue
 		} else {
-			fmt.Printf("HandlerData:查询队列失败,队列消息数量:%d", cnt)
+			logger.Get().Errorf("HandlerData:查询队列失败,队列消息数量:%d", cnt)
 			runtime.Gosched()
 		}
 	}
@@ -151,7 +146,7 @@ func (o *ModbusHandler) Handler() interface{} {
 	defer func() {
 		if err := recover(); err != nil {
 			go GetHandler().Handler()
-			fmt.Printf("MqttHandler.Handler:发生异常:%s", string(debug.Stack()))
+			logger.Get().Errorf("MqttHandler.Handler:发生异常:%s", string(debug.Stack()))
 		}
 	}()
 	for {
@@ -160,11 +155,11 @@ func (o *ModbusHandler) Handler() interface{} {
 			time.Sleep(10 * time.Millisecond)
 			continue
 		} else if quantity > 1000 {
-			fmt.Printf("数据队列累积过多,请注意优化,当前队列条数:%d", quantity)
+			logger.Get().Errorf("数据队列累积过多,请注意优化,当前队列条数:%d", quantity)
 		}
 		queueData, ok := msg.(*model.QueueData)
 		if !ok {
-			fmt.Println("Type assertion failed: msg is not of type model.QueueDat")
+			logger.Get().Errorln("Type assertion failed: msg is not of type model.QueueDat")
 			return nil
 		}
 		// 信息处理返回
@@ -177,11 +172,11 @@ func (o *ModbusHandler) Handler() interface{} {
 func parseData(data *model.QueueData) {
 	reg, dev, err := utils.GetDataByDeviceId(data.Id)
 	if err != nil {
-		fmt.Println("Error getting register and device:", err)
+		logger.Get().Errorln("Error getting register and device:", err)
 		return
 	}
 	toString := hex.EncodeToString(data.Value)
-	fmt.Println(data.Id + "----" + toString)
+	logger.Get().Println("Modbus Data: " + toString)
 	switch toString[0:2] {
 	case "fe":
 		switch toString[4:8] { // 开关灯
@@ -207,16 +202,18 @@ func parseData(data *model.QueueData) {
 				}
 			}
 			regions, err := utils.SaveRegionOnData(reg)
-			fmt.Println(regions)
+			logger.Get().Println(data.Id + "-----" + toString)
 			err = service.SaveData(regions)
 			if err != nil {
-				fmt.Println(err)
+				logger.Get().Errorln(err)
 				return
 			}
 		}
 	case "11":
+		logger.Get().Println("太阳能---" + toString)
 		switch toString[2:6] {
 		case "0336":
+			logger.Get().Println(data.Id + "太阳能" + toString)
 			batteryVoltage, _ := strconv.ParseInt(toString[6:10], 16, 64)
 			batteryCurrent, _ := strconv.ParseInt(toString[10:14], 16, 64)
 			batteryPlateVoltage, _ := strconv.ParseInt(toString[38:42], 16, 64)
@@ -234,7 +231,7 @@ func parseData(data *model.QueueData) {
 			regions, err := utils.SaveRegionOnData(reg)
 			err = service.SaveData(regions)
 			if err != nil {
-				fmt.Println(err)
+				logger.Get().Println("太阳能数据保存" + err.Error())
 				return
 			}
 			//电池
@@ -252,7 +249,7 @@ func parseData(data *model.QueueData) {
 	case "4c43":
 		bytes, err := hex.DecodeString(toString[4:])
 		if err != nil {
-			fmt.Println("Error decoding bytes:", err)
+			logger.Get().Errorln("Error decoding bytes:", err)
 			return
 		}
 		for i, device := range reg.Devices {
@@ -264,7 +261,7 @@ func parseData(data *model.QueueData) {
 		regions, err := utils.SaveRegionOnData(reg)
 		err = service.SaveData(regions)
 		if err != nil {
-			fmt.Println(err)
+			logger.Get().Errorln("心跳" + err.Error())
 			return
 		}
 	}

+ 56 - 0
logger/initLog.go

@@ -0,0 +1,56 @@
+package logger
+
+import (
+	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
+	"os"
+	"path/filepath"
+	"time"
+
+	log "github.com/sirupsen/logrus"
+)
+
+var globalLogger *log.Logger
+
+// Initialize 初始化全局 Logger 实例。
+func Initialize(logPath string) error {
+	// 创建日志目录
+	if err := os.MkdirAll(filepath.Dir(logPath), os.ModePerm); err != nil {
+		return err
+	}
+
+	// 使用 rotatelogs 进行日志轮转
+	writer, err := rotatelogs.New(
+		logPath+".%Y%m%d.log",                     // 文件名模式
+		rotatelogs.WithMaxAge(3*24*time.Hour),     // 最大保留时间3天
+		rotatelogs.WithRotationTime(24*time.Hour), // 每天轮转一次
+		rotatelogs.WithLinkName(logPath),          // 符号链接指向最新日志文件
+		rotatelogs.WithClock(rotatelogs.Local),    // 使用本地时区
+	)
+	if err != nil {
+		return err
+	}
+
+	// 设置日志格式为JSON
+	formatter := &log.JSONFormatter{
+		TimestampFormat: time.RFC3339,
+	}
+
+	// 创建一个新的 Logger 实例
+	logger := log.New()
+	logger.SetFormatter(formatter)
+	logger.SetLevel(log.InfoLevel)
+	logger.SetOutput(writer) // 设置输出到 rotatelogs 的 writer
+
+	// 将全局变量设置为新创建的 Logger 实例
+	globalLogger = logger
+
+	return nil
+}
+
+// Get 获取全局 Logger 实例。
+func Get() *log.Logger {
+	if globalLogger == nil {
+		panic("Logger not initialized")
+	}
+	return globalLogger
+}

+ 10 - 0
main.go

@@ -2,7 +2,9 @@ package main
 
 import (
 	"fmt"
+	"log"
 	"server/initialize"
+	"server/logger"
 	"server/router"
 	"server/work"
 )
@@ -10,6 +12,14 @@ import (
 func main() {
 	initRouter := router.InitRouter()
 
+	logPath := "./logs/app.log"
+	if err := logger.Initialize(logPath); err != nil {
+		log.Fatalf("Failed to initialize logger: %v", err)
+	}
+
+	// 使用全局 Logger
+	logger.Get().Info("Application started.")
+
 	work.MyJob()
 	initialize.InitInductanceTCP()
 	err := initRouter.Run(":8222")

+ 22 - 13
modbus/operate.go

@@ -1,24 +1,25 @@
 package modbus
 
 import (
+	"server/logger"
 	"server/model"
 	"server/utils"
 	"time"
 )
 
 // GetSunPowerInfo 获取太阳能信息
-func GetSunPowerInfo() {
-	for _, conn := range model.ConnectionMap {
-		//_, dev, err := utils.GetDataByDeviceId(id)
-		utils.WriteDevice(SolarEnergyData(), conn)
-		//if dev.IsSun && dev.State == 1 { //打开  并且在线
-		//	err = utils.WriteDevice(SolarEnergyData(), conn)
-		//	if err != nil {
-		//		return err
-		//	}
-		//}
+func GetSunPowerInfo() error {
+	for id, conn := range model.ConnectionMap {
+		_, dev, err := utils.GetDataByDeviceId(id)
+		if dev.IsSun && dev.State == 1 { //打开  并且在线
+			err = utils.WriteDevice(SolarEnergyData(), conn)
+			logger.Get().Info(dev.Sn + "SunPowerInfo 发送")
+			if err != nil {
+				return err
+			}
+		}
 	}
-	//return nil
+	return nil
 }
 
 // GetDeviceInfo 获取设备信息
@@ -31,7 +32,11 @@ func GetDeviceInfo() {
 
 // DealWithOffline 处理离线
 func DealWithOffline() {
-	regions, _ := utils.LoadData()
+	regions, err := utils.LoadData()
+	if err != nil {
+		logger.Get().Errorln("离线" + err.Error())
+		return
+	}
 	for i, region := range regions {
 		for i2, device := range region.Devices {
 			if time.Now().After(device.OnlineTime.Add(4*time.Minute)) && regions[i].Devices[i2].State != 0 {
@@ -39,5 +44,9 @@ func DealWithOffline() {
 			}
 		}
 	}
-	utils.SaveData("static/data.json", regions)
+	if len(regions) == 0 {
+		return
+	}
+	err = utils.SaveData("static/data.json", regions)
+	logger.Get().Errorln("离线保存" + err.Error())
 }

+ 8 - 39
service/cron.go

@@ -1,8 +1,7 @@
 package service
 
 import (
-	"fmt"
-	"log"
+	"server/logger"
 	"server/modbus"
 	"server/model"
 	"server/utils"
@@ -17,7 +16,7 @@ func (c Cron) RelayOnOffTimeTask() {
 	current := time.Now().Format("15:04")
 	devices, err := utils.GetOnlineDevices()
 	if err != nil {
-		_ = fmt.Errorf("LoadData err = %s", err.Error())
+		logger.Get().Errorf("LoadData err = %s", err.Error())
 		return
 	}
 	relayMap := make(map[string]map[int]int)
@@ -30,13 +29,9 @@ func (c Cron) RelayOnOffTimeTask() {
 			tmp = make(map[int]int)
 		}
 		relays := d.DeviceLoops
-		if err != nil {
-			fmt.Errorf(err.Error())
-			continue
-		}
 		rcTime, rlTime, err := utils.SunriseSunsetForChina(28.23, 113.05)
 		if err != nil {
-			log.Printf("SunriseSunsetForChina err = %s", err.Error())
+			logger.Get().Errorf("SunriseSunsetForChina err = %s", err.Error())
 			rcTime = "06:00"
 			rlTime = "18:00"
 		}
@@ -106,18 +101,18 @@ func (c Cron) RelayOnOffTimeTask() {
 
 		reg, dev, err := utils.GetDataByDeviceId(key)
 		if err != nil {
-			fmt.Printf("GetDataByDeviceId err = %s\n", err.Error())
+			logger.Get().Errorf("GetDataByDeviceId err = %s\n", err.Error())
 		}
 
 		for i, i2 := range value {
 			data := modbus.DeviceLoopSwitch(i, i2)
 			if model.ConnectionMap[key] == nil {
-				fmt.Errorf("设备连接丢失")
+				logger.Get().Errorf("设备连接丢失")
 			}
 			err := utils.WriteDevice(data, model.ConnectionMap[key])
 			time.Sleep(100 * time.Millisecond)
 			if err != nil {
-				fmt.Printf("WriteDevice err = %s\n", err.Error())
+				logger.Get().Errorf("WriteDevice err = %s\n", err.Error())
 			}
 
 			for j, loop := range dev.DeviceLoops {
@@ -135,37 +130,11 @@ func (c Cron) RelayOnOffTimeTask() {
 
 		data, err := utils.SaveRegionOnData(reg)
 		if err != nil {
-			fmt.Printf("SaveRegionOnData err = %s\n", err.Error())
+			logger.Get().Errorf("SaveRegionOnData err = %s\n", err.Error())
 		}
 		err = SaveData(data)
 		if err != nil {
-			fmt.Printf("SaveData err = %s\n", err.Error())
+			logger.Get().Errorf("SaveData err = %s\n", err.Error())
 		}
 	}
 }
-
-// UpdateDeviceRelayStatus 更新设备状态
-//func (c Cron) UpdateDeviceRelayStatus() {
-//	service := DeviceService{}
-//	devices := service.GetDevicesByModule1AndModule3()
-//	for _, d := range devices {
-//		//新2路开关,因固件与8路相同 这里要特殊处理下这里
-//		if *d.Module == 3 {
-//			d.CircuitNum = 8
-//		}
-//		Query(d.DeviceSn, d.CircuitNum)
-//	}
-//}
-//
-//// StatisticsDevice 设备统计
-//func (c Cron) StatisticsDevice() {
-//	statisticsService := DeviceOnlineDailyStatisticsService{}
-//	onlines := statisticsService.GetTotalDeviceOnline()
-//	for _, online := range onlines {
-//		err := statisticsService.UpdateStatisticsDevice(online)
-//		if err != nil {
-//			logger.Logger.Errorf("StatisticsDevice err = %s", err.Error())
-//		}
-//	}
-//}
-//

+ 9 - 11
service/device.go

@@ -3,15 +3,12 @@ package service
 import (
 	"fmt"
 	"server/dao"
+	"server/logger"
 	"server/modbus"
 	"server/model"
 	"server/utils"
 )
 
-func GetDeviceList() {
-	fmt.Println("Get device list.")
-}
-
 func SaveData(data []dao.Region) error {
 	if len(data) == 0 {
 		return fmt.Errorf("数据不能为空")
@@ -20,13 +17,14 @@ func SaveData(data []dao.Region) error {
 	if err != nil {
 		return err
 	}
-	return err
+	// Remove the redundant return err statement.
+	return nil // Return nil to indicate success
 }
 
 func DeviceLoopSwitch(deviceLoop dao.DeviceLoop) error {
 	data := modbus.DeviceLoopSwitch(deviceLoop.ID, deviceLoop.State)
-	fmt.Println(deviceLoop.DeviceId)
-	fmt.Println(model.ConnectionMap)
+	logger.Get().Println(deviceLoop.DeviceId)
+	logger.Get().Println(model.ConnectionMap)
 	if model.ConnectionMap[deviceLoop.DeviceId] == nil {
 		return fmt.Errorf("设备连接丢失")
 	}
@@ -49,7 +47,7 @@ func DeviceSwitch(req model.DeviceRequest) error {
 	}
 	err := utils.WriteDevice(data, model.ConnectionMap[req.Device.Sn])
 	if err != nil {
-		fmt.Printf("Write device error: %v\n", err)
+		logger.Get().Errorf("Write device error: %v\n", err)
 		return err
 	}
 	return nil
@@ -77,12 +75,12 @@ func DeviceBatchSwitch(req model.DevicesRequest) error {
 func GetOnlineDevice() (total, online int) {
 	devices, err := utils.GetOnlineDevices()
 	if err != nil {
-		fmt.Printf("GetOnlineDevices err = %s\n", err.Error())
+		logger.Get().Errorf("GetOnlineDevices err = %s\n", err.Error())
 		return
 	}
 	allDevices, err := utils.GetAllDevices()
 	if err != nil {
-		fmt.Printf("GetAllDevices err = %s\n", err.Error())
+		logger.Get().Errorf("GetAllDevices err = %s\n", err.Error())
 		return
 	}
 	return len(allDevices), len(devices)
@@ -104,7 +102,7 @@ func GetSunDevices() (devices []dao.Device, err error) {
 func UpdateRegisterAddress(deviceId string) error {
 	err := utils.WriteDevice(modbus.UpdateRegisterAddress(), model.ConnectionMap[deviceId])
 	if err != nil {
-		fmt.Printf("UpdateRegisterAddress error: %v\n", err)
+		logger.Get().Errorf("UpdateRegisterAddress error: %v\n", err)
 		return err
 	}
 	return nil

+ 426 - 0
static/data-fb.json

@@ -0,0 +1,426 @@
+[
+  {
+    "id": 1,
+    "name": "生活区",
+    "subRegion": null,
+    "devices": [
+      {
+        "id": 1,
+        "sn": "JM36xWRZq6PiwmKV",
+        "regionId": 1,
+        "name": "维修车间",
+        "genre": "八回路控制",
+        "state": 1,
+        "isSun": true,
+        "loopNumber": 8,
+        "onlineTime": "2025-01-19T09:43:59.91502361+08:00",
+        "deviceLoops": [
+          {
+            "id": 1,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路12",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 2,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路2",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 3,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路3",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 4,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路4",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 5,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路5",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 6,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路6",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 7,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路7",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 8,
+            "deviceId": "JM36xWRZq6PiwmKV",
+            "name": "回路8",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          }
+        ],
+        "sun": {
+          "deviceId": "JM36xWRZq6PiwmKV",
+          "batteryVoltage": 0,
+          "batteryCurrent": 0,
+          "batteryPlateVoltage": 0
+        }
+      },
+      {
+        "id": 3,
+        "sn": "JM453Sa4a8pdYdgV",
+        "regionId": 1,
+        "name": "洗车房",
+        "genre": "四回路控制",
+        "state": 1,
+        "isSun": false,
+        "loopNumber": 4,
+        "onlineTime": "2025-01-19T09:46:00.028035846+08:00",
+        "deviceLoops": [
+          {
+            "id": 1,
+            "deviceId": "JM453Sa4a8pdYdgV",
+            "name": "回路1",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 2,
+            "deviceId": "JM453Sa4a8pdYdgV",
+            "name": "回路2",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 3,
+            "deviceId": "JM453Sa4a8pdYdgV",
+            "name": "回路3",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 4,
+            "deviceId": "JM453Sa4a8pdYdgV",
+            "name": "回路4",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          }
+        ],
+        "sun": {
+          "deviceId": "",
+          "batteryVoltage": 0,
+          "batteryCurrent": 0,
+          "batteryPlateVoltage": 0
+        }
+      },
+      {
+        "id": 2,
+        "sn": "JM45U0zGDCMhgrxc",
+        "regionId": 1,
+        "name": "污泥厂大配电房",
+        "genre": "四回路控制",
+        "state": 1,
+        "isSun": false,
+        "loopNumber": 4,
+        "onlineTime": "2025-01-19T09:46:00.027293637+08:00",
+        "deviceLoops": [
+          {
+            "id": 1,
+            "deviceId": "JM45U0zGDCMhgrxc",
+            "name": "回路1",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 2,
+            "deviceId": "JM45U0zGDCMhgrxc",
+            "name": "回路2",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 3,
+            "deviceId": "JM45U0zGDCMhgrxc",
+            "name": "回路3",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 4,
+            "deviceId": "JM45U0zGDCMhgrxc",
+            "name": "回路4",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          }
+        ],
+        "sun": {
+          "deviceId": "",
+          "batteryVoltage": 0,
+          "batteryCurrent": 0,
+          "batteryPlateVoltage": 0
+        }
+      },
+      {
+        "id": 4,
+        "sn": "JM45S67eqnSKueAK",
+        "regionId": 1,
+        "name": "生活区",
+        "genre": "四回路控制",
+        "state": 1,
+        "isSun": false,
+        "loopNumber": 4,
+        "onlineTime": "2025-01-19T09:44:00.051568026+08:00",
+        "deviceLoops": [
+          {
+            "id": 1,
+            "deviceId": "JM45S67eqnSKueAK",
+            "name": "回路1",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 2,
+            "deviceId": "JM45S67eqnSKueAK",
+            "name": "回路2",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 3,
+            "deviceId": "JM45S67eqnSKueAK",
+            "name": "回路3",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 4,
+            "deviceId": "JM45S67eqnSKueAK",
+            "name": "回路4",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          }
+        ],
+        "sun": {
+          "deviceId": "",
+          "batteryVoltage": 0,
+          "batteryCurrent": 0,
+          "batteryPlateVoltage": 0
+        }
+      },
+      {
+        "id": 5,
+        "sn": "JM36g0RM0ivegAGK",
+        "regionId": 1,
+        "name": "入厂道路",
+        "genre": "八回路控制",
+        "state": 1,
+        "isSun": false,
+        "loopNumber": 8,
+        "onlineTime": "2025-01-19T09:46:00.039018537+08:00",
+        "deviceLoops": [
+          {
+            "id": 1,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路1",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 2,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路2",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 3,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路3",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 4,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路4",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 5,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路5",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 6,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路6",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 7,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路7",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          },
+          {
+            "id": 8,
+            "deviceId": "JM36g0RM0ivegAGK",
+            "name": "回路8",
+            "state": 0,
+            "timeCondition1OnTime": "关闭",
+            "timeCondition1OffTime": "关闭",
+            "timeCondition2OnTime": "关闭",
+            "timeCondition2OffTime": "关闭"
+          }
+        ],
+        "sun": {
+          "deviceId": "",
+          "batteryVoltage": 0,
+          "batteryCurrent": 0,
+          "batteryPlateVoltage": 0
+        }
+      }
+    ]
+  },
+  {
+    "id": 2,
+    "name": "股份公司进场上坡",
+    "subRegion": null,
+    "devices": []
+  },
+  {
+    "id": 3,
+    "name": "地磅房至污泥厂门口",
+    "subRegion": null,
+    "devices": []
+  },
+  {
+    "id": 4,
+    "name": "三角花园至油库",
+    "subRegion": null,
+    "devices": []
+  },
+  {
+    "id": 5,
+    "name": "地磅房至搅拌站",
+    "subRegion": null,
+    "devices": []
+  },
+  {
+    "id": 6,
+    "name": "搅拌站至三岔路口",
+    "subRegion": null,
+    "devices": []
+  },
+  {
+    "id": 7,
+    "name": "垃圾堆体道路",
+    "subRegion": null,
+    "devices": []
+  },
+  {
+    "id": 8,
+    "name": "污水进场道路",
+    "subRegion": null,
+    "devices": []
+  }
+]

+ 1 - 1
static/data.json

@@ -421,6 +421,6 @@
     "id": 8,
     "name": "污水进场道路",
     "subRegion": null,
-    "devices": [1]
+    "devices": []
   }
 ]

+ 65 - 36
utils/myTool.go

@@ -3,29 +3,46 @@ package utils
 import (
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"net"
 	"os"
+	"path/filepath"
 	"server/dao"
+	"server/logger"
 	"time"
 )
 
-const connDataFilePath = "static/devicePath.json"
 const dataFilePath = "static/data.json"
 
-// LoadData 从文件读取数据
-func LoadData() (regions []dao.Region, err error) {
+// LoadData 从文件中加载 Region 数据。
+func LoadData() ([]dao.Region, error) {
 	data, err := os.ReadFile(dataFilePath)
+
+	datafb, err := os.ReadFile("static/data-fb.json")
+	var regionsfb []dao.Region
+	if err := json.Unmarshal(datafb, &regionsfb); err != nil {
+		// 提供更多的上下文信息来帮助调试
+		return nil, fmt.Errorf("解析 JSON 失败: %v, 原始数据: %s", err, string(data))
+	}
+
 	if err != nil {
 		if os.IsNotExist(err) {
-			return nil, nil
+			return regionsfb, nil // 文件不存在时返回空数组
 		}
-		return nil, err
+		return nil, fmt.Errorf("读取文件失败: %v", err)
+	}
+
+	// 检查文件是否为空
+	if len(data) == 0 {
+		return regionsfb, nil // 如果文件为空,返回空数组
 	}
-	err = json.Unmarshal(data, &regions)
-	if err != nil {
-		return nil, err
 
+	var regions []dao.Region
+	if err := json.Unmarshal(data, &regions); err != nil {
+		// 提供更多的上下文信息来帮助调试
+		return nil, fmt.Errorf("解析 JSON 失败: %v, 原始数据: %s", err, string(data))
 	}
+
 	return regions, nil
 }
 
@@ -37,9 +54,9 @@ func GetOnlineDevices() (devices []dao.Device, err error) {
 
 	for _, region := range regions {
 		for _, device := range region.Devices {
-			//if device.State == 0 {
-			//	continue
-			//}
+			if device.State == 0 {
+				continue
+			}
 			devices = append(devices, device)
 		}
 	}
@@ -95,52 +112,64 @@ func SaveRegionOnData(data dao.Region) ([]dao.Region, error) {
 
 // SaveData 保存数据到文件
 func SaveData(path string, parameter interface{}) error {
+	// 如果 parameter 是 nil 或者是空的结构体/切片,可以选择不写入文件或返回错误。
+	if parameter == nil {
+		return fmt.Errorf("无法保存 nil 数据")
+	}
+
+	// 序列化数据
 	data, err := json.MarshalIndent(parameter, "", "  ")
 	if err != nil {
-		return err
+		return fmt.Errorf("JSON 序列化失败: %v", err)
 	}
-	return os.WriteFile(path, data, 0644)
-}
 
-// CalculateCircuitSum 计算给定回路数量的总和
-func CalculateCircuitSum(circuits int) (int, error) {
-	if circuits <= 0 {
-		return 0, fmt.Errorf("回路数量必须大于0")
+	// 创建临时文件用于原子写入
+	tempFile, err := ioutil.TempFile(filepath.Dir(path), "tmp-")
+	if err != nil {
+		return fmt.Errorf("创建临时文件失败: %v", err)
 	}
+	defer os.Remove(tempFile.Name()) // 确保即使出错也能清理临时文件
 
-	// 计算结果
-	result := (1 << circuits) - 1
+	// 写入临时文件
+	if _, err := tempFile.Write(data); err != nil {
+		tempFile.Close()
+		return fmt.Errorf("写入临时文件失败: %v", err)
+	}
+
+	// 确保所有数据都写入磁盘
+	if err := tempFile.Sync(); err != nil {
+		tempFile.Close()
+		return fmt.Errorf("同步临时文件失败: %v", err)
+	}
+
+	// 关闭临时文件
+	if err := tempFile.Close(); err != nil {
+		return fmt.Errorf("关闭临时文件失败: %v", err)
+	}
+
+	// 使用原子操作替换原始文件
+	if err := os.Rename(tempFile.Name(), path); err != nil {
+		return fmt.Errorf("替换文件失败: %v", err)
+	}
 
-	return result, nil
+	return nil
 }
 
 // WriteDevice 纯写
 func WriteDevice(frame []byte, conn net.Conn) error {
 	_, err := conn.Write(frame)
 	if err != nil {
-		fmt.Println("Error writing to connection:", err)
+		logger.Get().Errorln("Error writing to connection:", err)
 		return err
 	}
 	return nil
 }
 
-// ReadDevice 纯读
-func ReadDevice(conn net.Conn) (data []byte) {
-	buffer := make([]byte, 1024)
-	n, err := conn.Read(buffer)
-	if err != nil {
-		fmt.Println("Error reading from connection:", err)
-		return
-	}
-	fmt.Printf("Received %d bytes: %X\n", n, buffer[6:n])
-	return buffer
-}
-
 func WriteAndReadDevice(frame []byte, conn net.Conn, former, after int) (data []byte, err error) {
 	// 发送 Modbus RTU 帧
 	n, err := conn.Write(frame)
 	if err != nil {
-		fmt.Println("Error writing to connection:", err)
+		logger.Get().Errorln("Error writing to connection:", err)
 		return
 	}
 
@@ -151,7 +180,7 @@ func WriteAndReadDevice(frame []byte, conn net.Conn, former, after int) (data []
 	buffer := make([]byte, 1024)
 	n, err = conn.Read(buffer)
 	if err != nil {
-		fmt.Println("Error reading from connection:", err)
+		logger.Get().Errorln("Error reading from connection:", err)
 		return
 	}