1p3p: let charger handle session stop/restart (#7723)

This commit is contained in:
MarkusGH 2023-06-04 15:19:57 +02:00 • committed by GitHub
parent 38777d1e61
commit dd787ce52f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 16 deletions

View file

@ -1,6 +1,7 @@
package charger
import (
"errors"
"fmt"
"github.com/evcc-io/evcc/api"
@ -30,6 +31,7 @@ func NewConfigurableFromConfig(other map[string]interface{}) (api.Charger, error
Status, Enable, Enabled, MaxCurrent provider.Config
Identify, Phases1p3p *provider.Config
Wakeup *provider.Config
Tos bool
}
if err := util.DecodeOther(other, &cc); err != nil {
@ -66,6 +68,10 @@ func NewConfigurableFromConfig(other map[string]interface{}) (api.Charger, error
// decorate phases
var phases1p3p func(int) error
if cc.Phases1p3p != nil {
if !cc.Tos {
return nil, errors.New("1p3p does no longer handle disable/enable. Use tos: true to confirm you understand the consequences")
}
phases1p3pS, err := provider.NewIntSetterFromConfig("phases", *cc.Phases1p3p)
if err != nil {
return nil, fmt.Errorf("phases: %w", err)

View file

@ -52,7 +52,8 @@ const (
minActiveCurrent = 1.0 // minimum current at which a phase is treated as active
minActiveVoltage = 208 // minimum voltage at which a phase is treated as active
guardGracePeriod = 60 * time.Second // allow out of sync during this timespan
guardGracePeriod = 60 * time.Second // allow out of sync during this timespan
phaseSwitchDuration = 60 * time.Second // do not measure phases during this timespan
)
// elapsed is the time an expired timer will be set to
@ -131,6 +132,7 @@ type Loadpoint struct {
guardUpdated time.Time // Charger enabled/disabled timestamp
socUpdated time.Time // Soc updated timestamp (poll: connected)
vehicleDetect time.Time // Vehicle connected timestamp
phasesSwitched time.Time // Phase switch timestamp
vehicleDetectTicker *clock.Ticker
vehicleIdentifier string
@ -921,21 +923,16 @@ func (lp *Loadpoint) scalePhases(phases int) error {
}
if lp.GetPhases() != phases {
// disable charger - this will also stop the car charging using the api if available
if err := lp.setLimit(0, true); err != nil {
return err
}
// switch phases
if err := cp.Phases1p3p(phases); err != nil {
return fmt.Errorf("switch phases: %w", err)
}
// prevent premature measurement of active phases
lp.phasesSwitched = lp.clock.Now()
// update setting and reset timer
lp.setPhases(phases)
// allow pv mode to re-enable charger right away
lp.elapsePVTimer()
}
return nil
@ -1063,11 +1060,7 @@ func (lp *Loadpoint) pvMaxCurrent(mode api.ChargeMode, sitePower float64, batter
// switch phases up/down
if _, ok := lp.charger.(api.PhaseSwitcher); ok {
availablePower := -sitePower + lp.chargePower
// in case of scaling, keep charger disabled for this cycle
if lp.pvScalePhases(availablePower, minCurrent, maxCurrent) {
return 0
}
_ = lp.pvScalePhases(availablePower, minCurrent, maxCurrent)
}
// calculate target charge current from delta power and actual current
@ -1202,7 +1195,7 @@ func (lp *Loadpoint) updateChargeCurrents() {
lp.log.DEBUG.Printf("charge currents: %.3gA", lp.chargeCurrents)
lp.publish("chargeCurrents", lp.chargeCurrents)
if lp.charging() {
if lp.charging() && lp.phaseSwitchCompleted() {
var phases int
for _, i := range lp.chargeCurrents {
if i > minActiveCurrent {
@ -1411,6 +1404,11 @@ func (lp *Loadpoint) guardGracePeriodElapsed() bool {
return time.Since(lp.guardUpdated) > guardGracePeriod
}
// phaseSwitchCompleted returns true if phase switch has completed
func (lp *Loadpoint) phaseSwitchCompleted() bool {
return time.Since(lp.phasesSwitched) > phaseSwitchDuration
}
// Update is the main control function. It reevaluates meters and charger state
func (lp *Loadpoint) Update(sitePower float64, autoCharge, batteryBuffered, batteryStart bool, greenShare float64, effPrice, effCo2 *float64) {
lp.processTasks()

View file

@ -85,7 +85,7 @@ func (lp *Loadpoint) activePhases() int {
active := min(expect(vehicle), expect(physical), expect(measured))
// sanity check - we should not assume less active phases than actually measured
if measured > 0 && active < measured && lp.guardGracePeriodElapsed() {
if measured > 0 && active < measured {
lp.log.WARN.Printf("phase mismatch between %dp measured for %dp vehicle and %dp charger", measured, vehicle, physical)
}