-
-
Notifications
You must be signed in to change notification settings - Fork 529
/
loadpoint_phases.go
116 lines (92 loc) · 2.97 KB
/
loadpoint_phases.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package core
import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/keys"
)
// setConfiguredPhases sets the default phase configuration
func (lp *Loadpoint) setConfiguredPhases(phases int) {
lp.configuredPhases = phases
lp.publish(keys.PhasesConfigured, lp.configuredPhases)
lp.settings.SetInt(keys.PhasesConfigured, int64(lp.configuredPhases))
}
// setPhases sets the number of enabled phases without modifying the charger
func (lp *Loadpoint) setPhases(phases int) {
if lp.GetPhases() != phases {
lp.Lock()
lp.phases = phases
lp.Unlock()
// publish updated phase configuration
lp.publish(keys.PhasesEnabled, lp.phases)
// reset timer to disabled state
lp.resetPhaseTimer()
// measure phases after switching
lp.resetMeasuredPhases()
}
}
// resetMeasuredPhases resets measured phases to unknown on vehicle disconnect, phase switch or phase api call
func (lp *Loadpoint) resetMeasuredPhases() {
lp.Lock()
lp.measuredPhases = 0
lp.Unlock()
lp.publish(keys.PhasesActive, lp.ActivePhases())
}
// getMeasuredPhases provides synchronized access to measuredPhases
func (lp *Loadpoint) getMeasuredPhases() int {
lp.RLock()
defer lp.RUnlock()
return lp.measuredPhases
}
// assume 3p for switchable charger during startup
const unknownPhases = 3
func expect(phases int) int {
if phases > 0 {
return phases
}
return unknownPhases
}
// ActivePhases returns the number of expectedly active phases for the meter.
// If unknown for 1p3p chargers during startup it will assume 3p.
func (lp *Loadpoint) ActivePhases() int {
physical := lp.GetPhases()
vehicle := lp.getVehiclePhases()
measured := lp.getMeasuredPhases()
charger := lp.getChargerPhysicalPhases()
active := min(expect(vehicle), expect(physical), expect(measured), expect(charger))
// sanity check - we should not assume less active phases than actually measured
if measured > 0 && active < measured {
lp.log.WARN.Printf("phase mismatch between %dp measured for %dp vehicle and %dp charger", measured, vehicle, physical)
}
return active
}
// maxActivePhases returns the maximum number of active phases for the meter.
func (lp *Loadpoint) maxActivePhases() int {
physical := lp.GetPhases()
measured := lp.getMeasuredPhases()
vehicle := lp.getVehiclePhases()
charger := lp.getChargerPhysicalPhases()
// during 1p or unknown config, 1p measured is not a restriction
if physical <= 1 || vehicle == 1 {
measured = 0
}
// if 1p3p supported then assume configured limit or 3p
if lp.hasPhaseSwitching() {
physical = lp.configuredPhases
}
return min(expect(vehicle), expect(physical), expect(measured), expect(charger))
}
func (lp *Loadpoint) getVehiclePhases() int {
if vehicle := lp.GetVehicle(); vehicle != nil {
return vehicle.Phases()
}
return 0
}
func (lp *Loadpoint) getChargerPhysicalPhases() int {
if cc, ok := lp.charger.(api.PhaseDescriber); ok {
return cc.Phases()
}
return 0
}
func (lp *Loadpoint) hasPhaseSwitching() bool {
_, ok := lp.charger.(api.PhaseSwitcher)
return ok
}