115 lines
2.5 KiB
Go
115 lines
2.5 KiB
Go
package metrics
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/benbjohnson/clock"
|
|
)
|
|
|
|
type Accumulator struct {
|
|
clock clock.Clock
|
|
updated time.Time
|
|
energyMeter *float64 // kWh
|
|
returnEnergyMeter *float64 // kWh
|
|
Energy float64 `json:"energy"` // kWh
|
|
ReturnEnergy float64 `json:"returnEnergy"` // kWh
|
|
}
|
|
|
|
func WithClock(clock clock.Clock) func(*Accumulator) {
|
|
return func(m *Accumulator) {
|
|
m.clock = clock
|
|
}
|
|
}
|
|
|
|
func NewAccumulator(opt ...func(*Accumulator)) *Accumulator {
|
|
m := &Accumulator{clock: clock.New()}
|
|
for _, o := range opt {
|
|
o(m)
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (m *Accumulator) Updated() time.Time {
|
|
return m.updated
|
|
}
|
|
|
|
func (m *Accumulator) String() string {
|
|
b := new(bytes.Buffer)
|
|
fmt.Fprintf(b, "Accumulated: %.3fkWh energy, %.3fkWh return energy, updated: %v", m.Energy, m.ReturnEnergy, m.updated.Truncate(time.Second))
|
|
if m.energyMeter != nil || m.returnEnergyMeter != nil {
|
|
fmt.Fprintf(b, " energy total:")
|
|
if m.energyMeter != nil {
|
|
fmt.Fprintf(b, " %.3fkWh", *m.energyMeter)
|
|
}
|
|
if m.returnEnergyMeter != nil {
|
|
fmt.Fprintf(b, " %.3fkWh return energy", *m.returnEnergyMeter)
|
|
}
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
// SetEnergyMeterTotal adds the difference to the last total meter value in kWh
|
|
func (m *Accumulator) SetEnergyMeterTotal(v float64) {
|
|
defer func() {
|
|
m.updated = m.clock.Now()
|
|
m.energyMeter = new(v)
|
|
}()
|
|
|
|
if m.energyMeter == nil {
|
|
return
|
|
}
|
|
|
|
if v >= *m.energyMeter {
|
|
m.Energy += v - *m.energyMeter
|
|
}
|
|
}
|
|
|
|
// SetReturnEnergyMeterTotal adds the difference to the last total meter value in kWh
|
|
func (m *Accumulator) SetReturnEnergyMeterTotal(v float64) {
|
|
defer func() {
|
|
m.updated = m.clock.Now()
|
|
m.returnEnergyMeter = new(v)
|
|
}()
|
|
|
|
if m.returnEnergyMeter == nil {
|
|
return
|
|
}
|
|
|
|
if v >= *m.returnEnergyMeter {
|
|
m.ReturnEnergy += v - *m.returnEnergyMeter
|
|
}
|
|
}
|
|
|
|
// AddEnergy adds the given energy in kWh to the energy total
|
|
func (m *Accumulator) AddEnergy(v float64) {
|
|
defer func() { m.updated = m.clock.Now() }()
|
|
|
|
if m.updated.IsZero() {
|
|
return
|
|
}
|
|
|
|
m.Energy += v
|
|
}
|
|
|
|
// AddReturnEnergy adds the given energy in kWh to the return energy total
|
|
func (m *Accumulator) AddReturnEnergy(v float64) {
|
|
defer func() { m.updated = m.clock.Now() }()
|
|
|
|
if m.updated.IsZero() {
|
|
return
|
|
}
|
|
|
|
m.ReturnEnergy += v
|
|
}
|
|
|
|
// AddPower adds the given power in W, calculating the energy based on the time since the last update
|
|
func (m *Accumulator) AddPower(v float64) {
|
|
since := v * m.clock.Since(m.updated).Hours() / 1e3
|
|
if v >= 0 {
|
|
m.AddEnergy(since)
|
|
} else {
|
|
m.AddReturnEnergy(-since)
|
|
}
|
|
}
|