diff --git a/core/energy_metrics.go b/core/energy_metrics.go index 68934ed43..8534caeaa 100644 --- a/core/energy_metrics.go +++ b/core/energy_metrics.go @@ -11,13 +11,6 @@ type EnergyMetrics struct { currentCo2 *float64 // Current co2 emissions } -func NewEnergyMetrics() *EnergyMetrics { - em := &EnergyMetrics{} - em.Reset() - - return em -} - // SetEnvironment updates site information like solar share, price, co2 for use in later calculations func (em *EnergyMetrics) SetEnvironment(greenShare float64, effPrice, effCo2 *float64) { em.currentGreenShare = greenShare diff --git a/core/energy_metrics_test.go b/core/energy_metrics_test.go index 65ac760b7..006260ca4 100644 --- a/core/energy_metrics_test.go +++ b/core/energy_metrics_test.go @@ -117,7 +117,7 @@ func TestEnergyMetrics(t *testing.T) { } for _, tc := range tc { - s := NewEnergyMetrics() + var s EnergyMetrics for _, tc := range tc.steps { s.SetEnvironment(tc.greenShare, tc.effPrice, tc.effCo2) @@ -145,7 +145,7 @@ func TestEnergyMetrics(t *testing.T) { } // reset - s := NewEnergyMetrics() + var s EnergyMetrics s.SetEnvironment(1, f(1), f(1)) s.Update(1) s.Reset() diff --git a/core/loadpoint.go b/core/loadpoint.go index 8c720ac84..1e45db4a1 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -176,12 +176,12 @@ type Loadpoint struct { wakeUpTimer *Timer // Vehicle wake-up timeout // charge progress - vehicleSoc float64 // Vehicle Soc - chargeDuration time.Duration // Charge duration - sessionEnergy *EnergyMetrics // Stats for charged energy by session - chargeRemainingDuration time.Duration // Remaining charge duration - chargeRemainingEnergy float64 // Remaining charge energy in Wh - progress *Progress // Step-wise progress indicator + vehicleSoc float64 // Vehicle Soc + chargeDuration time.Duration // Charge duration + energyMetrics EnergyMetrics // Stats for charged energy by session + chargeRemainingDuration time.Duration // Remaining charge duration + chargeRemainingEnergy float64 // Remaining charge energy in Wh + progress *Progress // Step-wise progress indicator // session log db *session.DB @@ -307,12 +307,11 @@ func NewLoadpoint(log *util.Logger, settings *Settings) *Loadpoint { Mode: pollCharging, }, }, - Enable: ThresholdConfig{Delay: time.Minute, Threshold: 0}, // t, W - Disable: ThresholdConfig{Delay: 3 * time.Minute, Threshold: 0}, // t, W - sessionEnergy: NewEnergyMetrics(), - progress: NewProgress(0, 10), // soc progress indicator - coordinator: coordinator.NewDummy(), // dummy vehicle coordinator - tasks: util.NewQueue[Task](), // task queue + Enable: ThresholdConfig{Delay: time.Minute, Threshold: 0}, // t, W + Disable: ThresholdConfig{Delay: 3 * time.Minute, Threshold: 0}, // t, W + progress: NewProgress(0, 10), // soc progress indicator + coordinator: coordinator.NewDummy(), // dummy vehicle coordinator + tasks: util.NewQueue[Task](), // task queue } return lp @@ -475,8 +474,8 @@ func (lp *Loadpoint) evVehicleConnectHandler() { lp.log.INFO.Printf("car connected") // energy - lp.sessionEnergy.Reset() - lp.sessionEnergy.Publish("session", lp) + lp.energyMetrics.Reset() + lp.energyMetrics.Publish("session", lp) lp.publish(keys.ChargedEnergy, lp.getChargedEnergy()) // duration @@ -514,7 +513,7 @@ func (lp *Loadpoint) evVehicleDisconnectHandler() { lp.resetMeasuredPhases() // energy and duration - lp.sessionEnergy.Publish("session", lp) + lp.energyMetrics.Publish("session", lp) lp.publish(keys.ChargedEnergy, lp.getChargedEnergy()) lp.publish(keys.ConnectedDuration, lp.clock.Since(lp.connectedTime).Round(time.Second)) @@ -1580,7 +1579,7 @@ func (lp *Loadpoint) publishChargeProgress() { // workaround for Go-E resetting during disconnect, see // https://github.com/evcc-io/evcc/issues/5092 if f > lp.chargedAtStartup { - added, addedGreen := lp.sessionEnergy.Update(f - lp.chargedAtStartup) + added, addedGreen := lp.energyMetrics.Update(f - lp.chargedAtStartup) if telemetry.Enabled() && added > 0 { telemetry.UpdateEnergy(added, addedGreen) } @@ -1596,7 +1595,7 @@ func (lp *Loadpoint) publishChargeProgress() { } // TODO check if "session" prefix required? - lp.sessionEnergy.Publish("session", lp) + lp.energyMetrics.Publish("session", lp) // TODO deprecated: use sessionEnergy instead lp.publish(keys.ChargedEnergy, lp.getChargedEnergy()) @@ -1751,7 +1750,7 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, rates api.Rate lp.updateChargeVoltages() lp.phasesFromChargeCurrents() - lp.sessionEnergy.SetEnvironment(greenShare, effPrice, effCo2) + lp.energyMetrics.SetEnvironment(greenShare, effPrice, effCo2) // update ChargeRater here to make sure initial meter update is caught lp.bus.Publish(evChargeCurrent, lp.chargeCurrent) diff --git a/core/loadpoint_api.go b/core/loadpoint_api.go index 2570a9f0e..a37429df9 100644 --- a/core/loadpoint_api.go +++ b/core/loadpoint_api.go @@ -78,7 +78,7 @@ func (lp *Loadpoint) SetMode(mode api.ChargeMode) { func (lp *Loadpoint) getChargedEnergy() float64 { lp.RLock() defer lp.RUnlock() - return lp.sessionEnergy.TotalWh() + return lp.energyMetrics.TotalWh() } // GetPriority returns the loadpoint priority diff --git a/core/loadpoint_session.go b/core/loadpoint_session.go index c58bec59d..1c11b3850 100644 --- a/core/loadpoint_session.go +++ b/core/loadpoint_session.go @@ -3,6 +3,7 @@ package core import ( "github.com/evcc-io/evcc/api" "github.com/evcc-io/evcc/core/session" + "github.com/samber/lo" ) func (lp *Loadpoint) chargeMeterTotal() float64 { @@ -63,16 +64,15 @@ func (lp *Loadpoint) stopSession() { } if chargedEnergy := lp.getChargedEnergy() / 1e3; chargedEnergy > s.ChargedEnergy { - lp.sessionEnergy.Update(chargedEnergy) + lp.energyMetrics.Update(chargedEnergy) } - solarPerc := lp.sessionEnergy.SolarPercentage() - s.SolarPercentage = &solarPerc - s.Price = lp.sessionEnergy.Price() - s.PricePerKWh = lp.sessionEnergy.PricePerKWh() - s.Co2PerKWh = lp.sessionEnergy.Co2PerKWh() - s.ChargedEnergy = lp.sessionEnergy.TotalWh() / 1e3 - s.ChargeDuration = &lp.chargeDuration + s.SolarPercentage = lo.ToPtr(lp.energyMetrics.SolarPercentage()) + s.Price = lp.energyMetrics.Price() + s.PricePerKWh = lp.energyMetrics.PricePerKWh() + s.Co2PerKWh = lp.energyMetrics.Co2PerKWh() + s.ChargedEnergy = lp.energyMetrics.TotalWh() / 1e3 + s.ChargeDuration = lo.ToPtr(lp.chargeDuration.Abs()) lp.db.Persist(s) } diff --git a/core/loadpoint_session_test.go b/core/loadpoint_session_test.go index 412d4f5ff..946c6df72 100644 --- a/core/loadpoint_session_test.go +++ b/core/loadpoint_session_test.go @@ -38,11 +38,10 @@ func TestSession(t *testing.T) { cm := &EnergyDecorator{Meter: mm, MeterEnergy: me} lp := &Loadpoint{ - log: util.NewLogger("foo"), - clock: clock, - db: db, - chargeMeter: cm, - sessionEnergy: NewEnergyMetrics(), + log: util.NewLogger("foo"), + clock: clock, + db: db, + chargeMeter: cm, } // create session @@ -60,7 +59,7 @@ func TestSession(t *testing.T) { // stop charging clock.Add(time.Hour) - lp.sessionEnergy.Update(1.23) + lp.energyMetrics.Update(1.23) me.EXPECT().TotalEnergy().Return(1.0+lp.getChargedEnergy()/1e3, nil) // match chargedEnergy lp.stopSession() @@ -75,7 +74,7 @@ func TestSession(t *testing.T) { // stop charging - 2nd leg clock.Add(time.Hour) - lp.sessionEnergy.Update(lp.getChargedEnergy() * 2) + lp.energyMetrics.Update(lp.getChargedEnergy() * 2) me.EXPECT().TotalEnergy().Return(3.0, nil) // doesn't match chargedEnergy lp.stopSession() diff --git a/core/loadpoint_test.go b/core/loadpoint_test.go index 4adfbb80e..f19590d3a 100644 --- a/core/loadpoint_test.go +++ b/core/loadpoint_test.go @@ -156,19 +156,18 @@ func TestUpdatePowerZero(t *testing.T) { charger := api.NewMockCharger(ctrl) lp := &Loadpoint{ - log: util.NewLogger("foo"), - bus: evbus.New(), - clock: clck, - charger: charger, - chargeMeter: &Null{}, // silence nil panics - chargeRater: &Null{}, // silence nil panics - chargeTimer: &Null{}, // silence nil panics - wakeUpTimer: NewTimer(), - sessionEnergy: NewEnergyMetrics(), - minCurrent: minA, - maxCurrent: maxA, - phases: 1, - status: tc.status, // no status change + log: util.NewLogger("foo"), + bus: evbus.New(), + clock: clck, + charger: charger, + chargeMeter: &Null{}, // silence nil panics + chargeRater: &Null{}, // silence nil panics + chargeTimer: &Null{}, // silence nil panics + wakeUpTimer: NewTimer(), + minCurrent: minA, + maxCurrent: maxA, + phases: 1, + status: tc.status, // no status change } attachListeners(t, lp) @@ -402,13 +401,12 @@ func TestDisableAndEnableAtTargetSoc(t *testing.T) { progress: NewProgress(0, 10), // silence nil panics wakeUpTimer: NewTimer(), // silence nil panics // coordinator: coordinator.NewDummy(), // silence nil panics - minCurrent: minA, - maxCurrent: maxA, - vehicle: vehicle, // needed for targetSoc check - socEstimator: socEstimator, // instead of vehicle: vehicle, - mode: api.ModeNow, - sessionEnergy: NewEnergyMetrics(), - limitSoc: 90, // session limit + minCurrent: minA, + maxCurrent: maxA, + vehicle: vehicle, // needed for targetSoc check + socEstimator: socEstimator, // instead of vehicle: vehicle, + mode: api.ModeNow, + limitSoc: 90, // session limit Soc: SocConfig{ Poll: PollConfig{ Mode: pollConnected, // allow polling when connected @@ -472,19 +470,18 @@ func TestSetModeAndSocAtDisconnect(t *testing.T) { charger := api.NewMockCharger(ctrl) lp := &Loadpoint{ - log: util.NewLogger("foo"), - bus: evbus.New(), - clock: clock, - charger: charger, - chargeMeter: &Null{}, // silence nil panics - chargeRater: &Null{}, // silence nil panics - chargeTimer: &Null{}, // silence nil panics - wakeUpTimer: NewTimer(), - sessionEnergy: NewEnergyMetrics(), - minCurrent: minA, - maxCurrent: maxA, - status: api.StatusC, - Mode_: api.ModeOff, // default mode + log: util.NewLogger("foo"), + bus: evbus.New(), + clock: clock, + charger: charger, + chargeMeter: &Null{}, // silence nil panics + chargeRater: &Null{}, // silence nil panics + chargeTimer: &Null{}, // silence nil panics + wakeUpTimer: NewTimer(), + minCurrent: minA, + maxCurrent: maxA, + status: api.StatusC, + Mode_: api.ModeOff, // default mode } attachListeners(t, lp) @@ -540,18 +537,17 @@ func TestChargedEnergyAtDisconnect(t *testing.T) { rater := api.NewMockChargeRater(ctrl) lp := &Loadpoint{ - log: util.NewLogger("foo"), - bus: evbus.New(), - clock: clock, - charger: charger, - chargeMeter: &Null{}, // silence nil panics - chargeRater: rater, - chargeTimer: &Null{}, // silence nil panics - wakeUpTimer: NewTimer(), - sessionEnergy: NewEnergyMetrics(), - minCurrent: minA, - maxCurrent: maxA, - status: api.StatusC, + log: util.NewLogger("foo"), + bus: evbus.New(), + clock: clock, + charger: charger, + chargeMeter: &Null{}, // silence nil panics + chargeRater: rater, + chargeTimer: &Null{}, // silence nil panics + wakeUpTimer: NewTimer(), + minCurrent: minA, + maxCurrent: maxA, + status: api.StatusC, } attachListeners(t, lp) diff --git a/core/loadpoint_vehicle_test.go b/core/loadpoint_vehicle_test.go index d60cf8da7..ebe3bbb2b 100644 --- a/core/loadpoint_vehicle_test.go +++ b/core/loadpoint_vehicle_test.go @@ -37,20 +37,19 @@ func TestPublishSocAndRange(t *testing.T) { log := util.NewLogger("foo") lp := &Loadpoint{ - log: log, - bus: evbus.New(), - clock: clck, - charger: charger, - vehicle: vehicle, - chargeMeter: &Null{}, // silence nil panics - chargeRater: &Null{}, // silence nil panics - chargeTimer: &Null{}, // silence nil panics - socEstimator: soc.NewEstimator(log, charger, vehicle, false), - sessionEnergy: NewEnergyMetrics(), - minCurrent: minA, - maxCurrent: maxA, - phases: 1, - mode: api.ModeNow, + log: log, + bus: evbus.New(), + clock: clck, + charger: charger, + vehicle: vehicle, + chargeMeter: &Null{}, // silence nil panics + chargeRater: &Null{}, // silence nil panics + chargeTimer: &Null{}, // silence nil panics + socEstimator: soc.NewEstimator(log, charger, vehicle, false), + minCurrent: minA, + maxCurrent: maxA, + phases: 1, + mode: api.ModeNow, } // populate channels @@ -243,19 +242,18 @@ func TestReconnectVehicle(t *testing.T) { charger.EXPECT().Status().Return(api.StatusB, nil).AnyTimes() lp := &Loadpoint{ - log: util.NewLogger("foo"), - bus: evbus.New(), - clock: clck, - charger: charger, - chargeMeter: &Null{}, // silence nil panics - chargeRater: &Null{}, // silence nil panics - chargeTimer: &Null{}, // silence nil panics - wakeUpTimer: NewTimer(), - sessionEnergy: NewEnergyMetrics(), - minCurrent: minA, - maxCurrent: maxA, - phases: 1, - mode: api.ModeNow, + log: util.NewLogger("foo"), + bus: evbus.New(), + clock: clck, + charger: charger, + chargeMeter: &Null{}, // silence nil panics + chargeRater: &Null{}, // silence nil panics + chargeTimer: &Null{}, // silence nil panics + wakeUpTimer: NewTimer(), + minCurrent: minA, + maxCurrent: maxA, + phases: 1, + mode: api.ModeNow, } lp.coordinator = coordinator.NewAdapter(lp, coordinator.New(util.NewLogger("foo"), []api.Vehicle{vehicle}))