forked from evcc-io/evcc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmeter_average.go
100 lines (81 loc) · 2.18 KB
/
meter_average.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package meter
import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
)
func init() {
registry.Add("movingaverage", NewMovingAverageFromConfig)
}
// NewMovingAverageFromConfig creates api.Meter from config
func NewMovingAverageFromConfig(other map[string]interface{}) (api.Meter, error) {
cc := struct {
Decay float64
Meter struct {
capacity `mapstructure:",squash"`
Type string
Other map[string]interface{} `mapstructure:",remain"`
}
}{
Decay: 0.1,
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
m, err := NewFromConfig(cc.Meter.Type, cc.Meter.Other)
if err != nil {
return nil, err
}
mav := &MovingAverage{
decay: cc.Decay,
currentPowerG: m.CurrentPower,
}
meter, _ := NewConfigurable(mav.CurrentPower)
// decorate energy reading
var totalEnergy func() (float64, error)
if m, ok := m.(api.MeterEnergy); ok {
totalEnergy = m.TotalEnergy
}
// decorate battery reading
var batterySoc func() (float64, error)
if m, ok := m.(api.Battery); ok {
batterySoc = m.Soc
}
// decorate currents reading
var currents func() (float64, float64, float64, error)
if m, ok := m.(api.PhaseCurrents); ok {
currents = m.Currents
}
// decorate voltages reading
var voltages func() (float64, float64, float64, error)
if m, ok := m.(api.PhaseVoltages); ok {
voltages = m.Voltages
}
// decorate powers reading
var powers func() (float64, float64, float64, error)
if m, ok := m.(api.PhasePowers); ok {
powers = m.Powers
}
return meter.Decorate(totalEnergy, currents, voltages, powers, batterySoc, cc.Meter.capacity.Decorator()), nil
}
type MovingAverage struct {
decay float64
value *float64
currentPowerG func() (float64, error)
}
func (m *MovingAverage) CurrentPower() (float64, error) {
power, err := m.currentPowerG()
if err != nil {
return power, err
}
return m.add(power), nil
}
// modeled after https://github.com/VividCortex/ewma
// Add adds a value to the series and updates the moving average.
func (m *MovingAverage) add(value float64) float64 {
if m.value == nil {
m.value = &value
} else {
*m.value = (value * m.decay) + (*m.value * (1 - m.decay))
}
return *m.value
}