From 2271619ae191a2471548a90fd3769f838cf1363b Mon Sep 17 00:00:00 2001 From: wangqiyang Date: Wed, 29 Jul 2026 19:24:48 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=90=E5=88=B6=E6=95=85=E9=9A=9C12=E5=B0=8F?= =?UTF-8?q?=E6=97=B6=E5=86=85=E9=87=8D=E5=A4=8D=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/module/m9zTtyApi/cron.go | 32 +++++++--- internal/module/m9zTtyApi/cron_test.go | 81 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 internal/module/m9zTtyApi/cron_test.go diff --git a/internal/module/m9zTtyApi/cron.go b/internal/module/m9zTtyApi/cron.go index 586f1be..d2dc10e 100644 --- a/internal/module/m9zTtyApi/cron.go +++ b/internal/module/m9zTtyApi/cron.go @@ -21,7 +21,8 @@ var historyLock sync.Mutex var filePath = system.GetPathOfProgram() + "data/data.json" const ( - maxItems = 50 + maxItems = 50 + faultDuplicateWindow = 12 * time.Hour ) func ScanM9z() { @@ -105,19 +106,15 @@ func addData(newItem M9zFaultHistory) error { return gerror.Wrap(err, "readData") } + if newItem.FaultTime.IsZero() { + newItem.FaultTime = time.Now() + } for _, item := range items { - if item.CommUid == newItem.CommUid && - item.LoopIdx == newItem.LoopIdx && - item.FaultCode == newItem.FaultCode && - item.FaultMsg == newItem.FaultMsg && - item.OperateStatus == 0 { + if isDuplicateFaultWithinWindow(item, newItem) { return nil } } - if newItem.FaultTime.IsZero() { - newItem.FaultTime = time.Now() - } items = append(items, newItem) if len(items) > maxItems { @@ -136,6 +133,23 @@ func addData(newItem M9zFaultHistory) error { return nil } +func isDuplicateFaultWithinWindow(item, newItem M9zFaultHistory) bool { + if item.CommUid != newItem.CommUid || + item.LoopIdx != newItem.LoopIdx || + item.FaultCode != newItem.FaultCode || + item.FaultMsg != newItem.FaultMsg { + return false + } + if item.FaultTime.IsZero() || newItem.FaultTime.IsZero() { + return false + } + diff := newItem.FaultTime.Sub(item.FaultTime) + if diff < 0 { + diff = -diff + } + return diff < faultDuplicateWindow +} + func deleteById(id int) error { historyLock.Lock() defer historyLock.Unlock() diff --git a/internal/module/m9zTtyApi/cron_test.go b/internal/module/m9zTtyApi/cron_test.go new file mode 100644 index 0000000..18316d7 --- /dev/null +++ b/internal/module/m9zTtyApi/cron_test.go @@ -0,0 +1,81 @@ +package m9zApi + +import ( + "path/filepath" + "testing" + "time" +) + +func useTempFaultHistoryFile(t *testing.T) { + t.Helper() + + oldFilePath := filePath + filePath = filepath.Join(t.TempDir(), "data.json") + t.Cleanup(func() { + filePath = oldFilePath + }) +} + +func TestAddDataSkipsDuplicateFaultWithin12Hours(t *testing.T) { + useTempFaultHistoryFile(t) + + now := time.Date(2026, 7, 29, 8, 0, 0, 0, time.UTC) + item := M9zFaultHistory{ + CommUid: "device-1", + LoopIdx: 1, + FaultCode: "01", + FaultMsg: "short circuit", + FaultTime: now, + } + if err := addData(item); err != nil { + t.Fatalf("addData first item error = %v", err) + } + + duplicate := item + duplicate.Voltage = 230 + duplicate.FaultTime = now.Add(faultDuplicateWindow - time.Second) + if err := addData(duplicate); err != nil { + t.Fatalf("addData duplicate item error = %v", err) + } + + items, err := readData() + if err != nil { + t.Fatalf("readData error = %v", err) + } + if len(items) != 1 { + t.Fatalf("len(items) = %d, want 1", len(items)) + } + if !items[0].FaultTime.Equal(now) { + t.Fatalf("FaultTime = %v, want %v", items[0].FaultTime, now) + } +} + +func TestAddDataAllowsDuplicateFaultAfter12Hours(t *testing.T) { + useTempFaultHistoryFile(t) + + now := time.Date(2026, 7, 29, 8, 0, 0, 0, time.UTC) + item := M9zFaultHistory{ + CommUid: "device-1", + LoopIdx: 1, + FaultCode: "01", + FaultMsg: "short circuit", + FaultTime: now, + } + if err := addData(item); err != nil { + t.Fatalf("addData first item error = %v", err) + } + + duplicate := item + duplicate.FaultTime = now.Add(faultDuplicateWindow) + if err := addData(duplicate); err != nil { + t.Fatalf("addData after window error = %v", err) + } + + items, err := readData() + if err != nil { + t.Fatalf("readData error = %v", err) + } + if len(items) != 2 { + t.Fatalf("len(items) = %d, want 2", len(items)) + } +}