You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
3.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package m9zApi
import (
"encoding/json"
"fmt"
"github.com/towgo/towgo/errors/terror"
"github.com/towgo/towgo/lib/system"
"os"
"path/filepath"
"sort"
"sync"
"tgk-touch/internal/global"
"tgk-touch/internal/library/m9z"
"time"
)
var l sync.Mutex
var filePath = system.GetPathOfProgram() + "data/data.json" // JSON 文件路径
const (
maxItems = 50 // 最大存储条数
)
func ScanM9z() {
tryLock := l.TryLock()
if !tryLock {
return
}
defer l.Unlock()
/** 挨个查询是否有报警*/
cuid := deviceInfo["deviceId"].(string)
for i := 0; i < 10; i++ {
read, err := m9z.SubLoopParametersRead(cuid, uint(i))
if err != nil {
g.Log().Error("sub loop parameters read error:", err)
continue
}
if read == nil {
continue
}
if read.AlarmStatus != 0 {
var mph M9zFaultHistory
mph.CommUid = cuid
mph.LoopIdx = uint(i) + 1
mph.FaultCode = read.AlarmCode
mph.Voltage = read.DCVoltage
mph.FaultTime = time.Now()
switch read.AlarmStatus {
case 1:
mph.FaultMsg = "欠压/短路故障"
break
case 2:
mph.FaultMsg = "过压/开路故障"
break
case 8:
mph.FaultMsg = "电源故障"
break
case 9:
mph.FaultMsg = "欠压/电源故障"
break
default:
mph.FaultMsg = "未知异常"
}
err = addData(mph)
if err != nil {
g.Log().Error(terror.Wrap(err, "create error"))
}
}
}
}
// 读取现有数据(如果文件不存在则返回空切片)
func readData() ([]M9zFaultHistory, error) {
if _, err := os.Stat(filePath); os.IsNotExist(err) {
_, err := createFileWithPath(filePath)
if err != nil {
return nil, terror.Wrap(err, "create file error")
}
return []M9zFaultHistory{}, nil // 文件不存在,返回空切片
}
data, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("读取文件失败: %v", err)
}
var items []M9zFaultHistory
if len(data) > 0 {
if err := json.Unmarshal(data, &items); err != nil {
return nil, fmt.Errorf("解析 JSON 失败: %v", err)
}
}
// 确保ID匹配索引+1处理旧数据或缺失ID
for i := range items {
items[i].ID = int64(i + 1)
}
return items, nil
}
// 写入数据到 JSON 文件
func writeData(items []M9zFaultHistory) error {
data, err := json.MarshalIndent(items, "", " ")
if err != nil {
return fmt.Errorf("序列化 JSON 失败: %v", err)
}
return os.WriteFile(filePath, data, 0644)
}
// 新增数据(自动处理容量限制)
func addData(newItem M9zFaultHistory) error {
// 1. 读取现有数据
items, err := readData()
if err != nil {
return terror.Wrap(err, "readData")
}
// 2. 追加新数据
items = append(items, newItem)
// 3. 检查容量,如果超过 maxItems 则删除最早的数据(按时间排序)
if len(items) > maxItems {
// 按 Timestamp 排序(最早的在前)
sort.Slice(items, func(i, j int) bool {
return items[i].FaultTime.Before(items[j].FaultTime)
})
// 删除最早的数据(保留最新的 maxItems 条)
items = items[1:]
for i, _ := range items {
items[i].ID = int64(i + 1)
}
}
// 4. 写回文件
err = writeData(items)
if err != nil {
return terror.Wrap(err, "writeData")
}
return nil
}
// 按ID删除数据
func deleteById(id int) error {
items, err := readData()
if err != nil {
return terror.Wrap(err, "readData")
}
if id < 1 || id > len(items) {
return fmt.Errorf("ID %d 超出范围", id)
}
// 删除指定索引的数据id-1
items = append(items[:id-1], items[id:]...)
// 重新分配ID确保后续数据ID连续
for i := id - 1; i < len(items); i++ {
items[i].ID = int64(i + 1)
}
return writeData(items)
}
func createFileWithPath(filePath string) (*os.File, error) {
// 创建所有必需的父目录(使用 0755 权限)
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return nil, err
}
// 创建并打开文件(如果已存在则截断)
return os.Create(filePath)
}