From 42ca83d3c0b5d6e4ccc67a5754b7889bad8ca14a Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 3 Dec 2022 15:07:12 +0100 Subject: [PATCH] Sessions: fix odometer not persisted --- core/db/db.go | 3 --- core/db/session.go | 9 ------- core/loadpoint.go | 15 ++++++++--- core/loadpoint_session.go | 55 +++++++++++++++++++++++++-------------- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/core/db/db.go b/core/db/db.go index 9aee1d250..4222e24c2 100644 --- a/core/db/db.go +++ b/core/db/db.go @@ -1,8 +1,6 @@ package db import ( - "time" - serverdb "github.com/evcc-io/evcc/server/db" "github.com/evcc-io/evcc/util" "gorm.io/gorm" @@ -35,7 +33,6 @@ func New(name string) (*DB, error) { func (s *DB) Session(meter float64) *Session { t := Session{ Loadpoint: s.name, - Created: time.Now(), MeterStart: meter, } diff --git a/core/db/session.go b/core/db/session.go index 9a94a1ff9..6aff7b518 100644 --- a/core/db/session.go +++ b/core/db/session.go @@ -31,15 +31,6 @@ type Session struct { ChargedEnergy float64 `json:"chargedEnergy" csv:"Charged Energy (kWh)" gorm:"column:charged_kwh"` } -// Stop stops charging session with end meter reading and due total amount -func (t *Session) Stop(chargedWh, total float64) { - if chargedEnergy := chargedWh / 1e3; chargedEnergy > t.ChargedEnergy { - t.ChargedEnergy = chargedEnergy - } - t.MeterStop = total - t.Finished = time.Now() -} - // Sessions is a list of sessions type Sessions []Session diff --git a/core/loadpoint.go b/core/loadpoint.go index d68f156a8..e424710dd 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -387,7 +387,12 @@ func (lp *LoadPoint) evChargeStartHandler() { // soc update reset lp.socUpdated = time.Time{} - lp.startSession() + // set created when first charging session segment starts + lp.updateSession(func(session *db.Session) { + if session.Created.IsZero() { + session.Created = lp.clock.Now() + } + }) } // evChargeStopHandler sends external stop event @@ -432,15 +437,17 @@ func (lp *LoadPoint) evVehicleConnectHandler() { // immediately allow pv mode activity lp.elapsePVTimer() + + // create charging session + lp.createSession() } // evVehicleDisconnectHandler sends external start event func (lp *LoadPoint) evVehicleDisconnectHandler() { lp.log.INFO.Println("car disconnected") - // ensure session is persisted and closed before vehicle is changed - lp.stopSession() - lp.finalizeSession() + // session is persisted during evChargeStopHandler which runs before + lp.clearSession() // phases are unknown when vehicle disconnects lp.resetMeasuredPhases() diff --git a/core/loadpoint_session.go b/core/loadpoint_session.go index f37d8f28f..c14bda722 100644 --- a/core/loadpoint_session.go +++ b/core/loadpoint_session.go @@ -1,6 +1,8 @@ package core import ( + "time" + "github.com/evcc-io/evcc/api" "github.com/evcc-io/evcc/core/db" ) @@ -20,39 +22,50 @@ func (lp *LoadPoint) chargeMeterTotal() float64 { return f } -func (lp *LoadPoint) startSession() { +// createSession creates a charging session. The created timestamp is empty until set by evChargeStartHandler. +// The session is not persisted yet. That will only happen when stopSession is called. +func (lp *LoadPoint) createSession() { // test guard - if lp.db == nil { + if lp.db == nil || lp.session != nil { return } - if lp.session == nil { - lp.session = lp.db.Session(lp.chargeMeterTotal()) + lp.session = lp.db.Session(lp.chargeMeterTotal()) - if lp.vehicle != nil { - lp.session.Vehicle = lp.vehicle.Title() - } - - if c, ok := lp.charger.(api.Identifier); ok { - if id, err := c.Identify(); err == nil { - lp.session.Identifier = id - } - } - - // TODO remove - lp.log.DEBUG.Println("session started") - - lp.db.Persist(lp.session) + if lp.vehicle != nil { + lp.session.Vehicle = lp.vehicle.Title() } + + if c, ok := lp.charger.(api.Identifier); ok { + if id, err := c.Identify(); err == nil { + lp.session.Identifier = id + } + } + + // TODO remove + lp.log.DEBUG.Println("session started") } +// stopSession ends a charging session segment and persists the session. func (lp *LoadPoint) stopSession() { // test guard if lp.db == nil || lp.session == nil { return } - lp.session.Stop(lp.getChargedEnergy(), lp.chargeMeterTotal()) + // abort the session if charging has never started + if lp.session.Created.IsZero() { + // TODO remove + lp.log.DEBUG.Println("session aborted") + return + } + + lp.session.Finished = time.Now() + lp.session.MeterStop = lp.chargeMeterTotal() + + if chargedEnergy := lp.getChargedEnergy() / 1e3; chargedEnergy > lp.session.ChargedEnergy { + lp.session.ChargedEnergy = chargedEnergy + } // TODO remove lp.log.DEBUG.Println("session stopped") @@ -62,6 +75,7 @@ func (lp *LoadPoint) stopSession() { type sessionOption func(*db.Session) +// updateSession updates any parameter of a charging session and persists the session. func (lp *LoadPoint) updateSession(opts ...sessionOption) { // test guard if lp.db == nil || lp.session == nil { @@ -78,7 +92,8 @@ func (lp *LoadPoint) updateSession(opts ...sessionOption) { lp.db.Persist(lp.session) } -func (lp *LoadPoint) finalizeSession() { +// clearSession clears the charging session without persisting it. +func (lp *LoadPoint) clearSession() { // test guard if lp.db == nil { return