125 lines
2.7 KiB
Go
125 lines
2.7 KiB
Go
package model
|
||
|
||
import (
|
||
"fmt"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// DataPointID 数据点标识
|
||
type DataPointID struct {
|
||
DeviceID string // 设备ID
|
||
MetricCode string // 指标代码
|
||
Labels map[string]string // 自定义标签
|
||
}
|
||
|
||
// String 返回数据点标识的字符串表示
|
||
func (id DataPointID) String() string {
|
||
return fmt.Sprintf("%s:%s:%v", id.DeviceID, id.MetricCode, id.Labels)
|
||
}
|
||
|
||
// DataValue 数据值
|
||
type DataValue struct {
|
||
Timestamp time.Time // 时间戳
|
||
Value interface{} // 支持 int64 或 float64
|
||
}
|
||
|
||
// CircularBuffer 环形缓冲区
|
||
type CircularBuffer struct {
|
||
Values [30]DataValue // 固定大小为30的环形缓冲区
|
||
Head int // 当前写入位置
|
||
Lock sync.RWMutex // 细粒度锁
|
||
}
|
||
|
||
// NewCircularBuffer 创建一个新的环形缓冲区
|
||
func NewCircularBuffer() *CircularBuffer {
|
||
return &CircularBuffer{
|
||
Head: -1, // 初始化为-1,表示缓冲区为空
|
||
}
|
||
}
|
||
|
||
// Write 写入一个新的数据值
|
||
func (cb *CircularBuffer) Write(value DataValue) {
|
||
cb.Lock.Lock()
|
||
defer cb.Lock.Unlock()
|
||
|
||
cb.Head = (cb.Head + 1) % len(cb.Values)
|
||
cb.Values[cb.Head] = value
|
||
}
|
||
|
||
// Read 读取所有数据值,按时间顺序返回
|
||
func (cb *CircularBuffer) Read() []DataValue {
|
||
cb.Lock.RLock()
|
||
defer cb.Lock.RUnlock()
|
||
|
||
if cb.Head == -1 {
|
||
return []DataValue{} // 缓冲区为空
|
||
}
|
||
|
||
result := make([]DataValue, 0, len(cb.Values))
|
||
|
||
// 从最旧的数据开始
|
||
oldest := (cb.Head + 1) % len(cb.Values)
|
||
|
||
// 如果缓冲区未满,oldest可能指向未初始化的元素
|
||
// 我们需要检查并跳过这些元素
|
||
for i := 0; i < len(cb.Values); i++ {
|
||
idx := (oldest + i) % len(cb.Values)
|
||
// 跳过未初始化的元素
|
||
if cb.Values[idx].Timestamp.IsZero() {
|
||
continue
|
||
}
|
||
result = append(result, cb.Values[idx])
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// GetLatest 获取最新的数据值
|
||
func (cb *CircularBuffer) GetLatest() (DataValue, bool) {
|
||
cb.Lock.RLock()
|
||
defer cb.Lock.RUnlock()
|
||
|
||
if cb.Head == -1 {
|
||
return DataValue{}, false // 缓冲区为空
|
||
}
|
||
|
||
return cb.Values[cb.Head], true
|
||
}
|
||
|
||
// GetDuration 获取最新值的持续时间
|
||
func (cb *CircularBuffer) GetDuration() time.Duration {
|
||
cb.Lock.RLock()
|
||
defer cb.Lock.RUnlock()
|
||
|
||
if cb.Head == -1 {
|
||
return 0 // 缓冲区为空
|
||
}
|
||
|
||
latest := cb.Values[cb.Head]
|
||
|
||
// 如果只有一个值,无法计算持续时间
|
||
if len(cb.Values) == 1 {
|
||
return 0
|
||
}
|
||
|
||
// 查找前一个不同的值
|
||
for i := 1; i < len(cb.Values); i++ {
|
||
idx := (cb.Head - i + len(cb.Values)) % len(cb.Values)
|
||
prev := cb.Values[idx]
|
||
|
||
// 跳过未初始化的元素
|
||
if prev.Timestamp.IsZero() {
|
||
continue
|
||
}
|
||
|
||
// 如果值不同,计算持续时间
|
||
if prev.Value != latest.Value {
|
||
return latest.Timestamp.Sub(prev.Timestamp)
|
||
}
|
||
}
|
||
|
||
// 所有值都相同,无法计算持续时间
|
||
return 0
|
||
}
|