This commit is contained in:
qsc
2026-07-13 00:44:09 +08:00
parent 34ec65c8b5
commit ef96af7f21
22 changed files with 1827 additions and 587 deletions
+1
View File
@@ -119,6 +119,7 @@ func (e *Engine) collect(ctx context.Context, p pg.PointRow) {
value = &v
quality = 0
reason = nil
e.manager.MarkConnected(p.DeviceID)
} else {
reasonText = "read_error"
reason = &reasonText
+11 -1
View File
@@ -100,8 +100,18 @@ func (m *Manager) Times(id uuid.UUID) (online, offline *time.Time) {
}
func (m *Manager) MarkDisconnected(id uuid.UUID) {
m.mu.Lock()
if m.statuses[id] != "disconnected" {
m.lastOffline[id] = time.Now()
}
m.statuses[id] = "disconnected"
m.lastOffline[id] = time.Now()
m.mu.Unlock()
}
func (m *Manager) MarkConnected(id uuid.UUID) {
m.mu.Lock()
if m.statuses[id] != "connected" {
m.lastOnline[id] = time.Now()
}
m.statuses[id] = "connected"
m.mu.Unlock()
}
func (m *Manager) setStatus(id uuid.UUID, s string) {
+50
View File
@@ -0,0 +1,50 @@
package collector
import (
"github.com/google/uuid"
"testing"
"time"
)
func TestManagerStatusRecoversAfterSuccessfulRead(t *testing.T) {
m := NewManager(nil, nil)
id := uuid.New()
m.MarkConnected(id)
online, offline := m.Times(id)
if m.Status(id) != "connected" || online == nil || offline != nil {
t.Fatalf("expected connected status with online timestamp, got status=%q online=%v offline=%v", m.Status(id), online, offline)
}
firstOnline := *online
m.MarkDisconnected(id)
if m.Status(id) != "disconnected" {
t.Fatalf("expected disconnected status, got %q", m.Status(id))
}
_, offline = m.Times(id)
if offline == nil {
t.Fatal("expected offline timestamp after disconnect")
}
time.Sleep(2 * time.Millisecond)
m.MarkConnected(id)
online, offline = m.Times(id)
if m.Status(id) != "connected" || online == nil || offline == nil {
t.Fatalf("expected recovered connected status, got status=%q online=%v offline=%v", m.Status(id), online, offline)
}
if !online.After(firstOnline) {
t.Fatalf("expected reconnect to refresh online timestamp: first=%v current=%v", firstOnline, *online)
}
}
func TestManagerRepeatedConnectedDoesNotRefreshOnlineTimestamp(t *testing.T) {
m := NewManager(nil, nil)
id := uuid.New()
m.MarkConnected(id)
first, _ := m.Times(id)
m.MarkConnected(id)
second, _ := m.Times(id)
if first == nil || second == nil || !first.Equal(*second) {
t.Fatalf("repeated connected mark changed online timestamp: first=%v second=%v", first, second)
}
}
+7 -3
View File
@@ -19,9 +19,13 @@ type Result struct {
TS time.Time
}
// REAL values are compared with a fixed protocol precision. The tolerance is
// intentionally not part of the write-point configuration anymore.
const realReadbackPrecision = 0.0001
func (e *Engine) Execute(ctx context.Context, p pg.PointRow, value float64) (Result, error) {
if !p.Enabled || !p.WriteEnabled {
return Result{}, errors.New("写入点未启用或写入开关关闭")
if !p.WriteEnabled {
return Result{}, errors.New("写入点未允许写入")
}
c, err := e.Manager.Connection(ctx, p.DeviceID)
if err != nil {
@@ -39,7 +43,7 @@ func (e *Engine) Execute(ctx context.Context, p pg.PointRow, value float64) (Res
}
ok := actual == value
if dt == protocol.Real {
ok = math.Abs(actual-value) <= p.ReadbackTolerance
ok = math.Abs(actual-value) <= realReadbackPrecision
}
if ok {
return Result{value, actual, time.Now()}, nil