Sessions: use meter energy reading to correct session charged energy (#6197)
This commit is contained in:
parent
b63bcea788
commit
446a7c4408
4 changed files with 115 additions and 22 deletions
|
|
@ -20,13 +20,24 @@ type Database interface {
|
|||
|
||||
// New creates a database storage driver
|
||||
func New(name string) (*DB, error) {
|
||||
db := &DB{
|
||||
db := serverdb.Instance
|
||||
|
||||
// TODO deprecate
|
||||
var err error
|
||||
if table := "transactions"; db.Migrator().HasTable(table) {
|
||||
err = db.Migrator().RenameTable(table, new(Session))
|
||||
}
|
||||
if err == nil {
|
||||
err = db.AutoMigrate(new(Session))
|
||||
}
|
||||
|
||||
sessiondb := &DB{
|
||||
log: util.NewLogger("db"),
|
||||
db: serverdb.Instance,
|
||||
db: db,
|
||||
name: name,
|
||||
}
|
||||
|
||||
return db, nil
|
||||
return sessiondb, err
|
||||
}
|
||||
|
||||
// Session creates a charging session
|
||||
|
|
@ -45,3 +56,10 @@ func (s *DB) Persist(session interface{}) {
|
|||
s.log.ERROR.Printf("persist: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Return sessions
|
||||
func (s *DB) Sessions() (Sessions, error) {
|
||||
var res Sessions
|
||||
tx := s.db.Find(&res)
|
||||
return res, tx.Error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/core/db"
|
||||
)
|
||||
|
|
@ -55,10 +53,15 @@ func (lp *Loadpoint) stopSession() {
|
|||
return
|
||||
}
|
||||
|
||||
lp.session.Finished = time.Now()
|
||||
lp.session.Finished = lp.clock.Now()
|
||||
lp.session.MeterStop = lp.chargeMeterTotal()
|
||||
|
||||
if chargedEnergy := lp.getChargedEnergy() / 1e3; chargedEnergy > lp.session.ChargedEnergy {
|
||||
chargedEnergy := lp.getChargedEnergy() / 1e3
|
||||
if delta := lp.session.MeterStop - lp.session.MeterStart; delta < chargedEnergy && lp.session.MeterStart*lp.session.MeterStop > 0 {
|
||||
chargedEnergy = delta
|
||||
}
|
||||
|
||||
if chargedEnergy > lp.session.ChargedEnergy {
|
||||
lp.session.ChargedEnergy = chargedEnergy
|
||||
}
|
||||
|
||||
|
|
|
|||
87
core/loadpoint_session_test.go
Normal file
87
core/loadpoint_session_test.go
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/benbjohnson/clock"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
coredb "github.com/evcc-io/evcc/core/db"
|
||||
"github.com/evcc-io/evcc/mock"
|
||||
serverdb "github.com/evcc-io/evcc/server/db"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSession(t *testing.T) {
|
||||
var err error
|
||||
serverdb.Instance, err = serverdb.New("sqlite", ":memory:")
|
||||
assert.NoError(t, err)
|
||||
|
||||
db, err := coredb.New("foo")
|
||||
assert.NoError(t, err)
|
||||
|
||||
clock := clock.NewMock()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mm := mock.NewMockMeter(ctrl)
|
||||
me := mock.NewMockMeterEnergy(ctrl)
|
||||
|
||||
type EnergyDecorator struct {
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}
|
||||
|
||||
cm := &EnergyDecorator{Meter: mm, MeterEnergy: me}
|
||||
|
||||
lp := &Loadpoint{
|
||||
clock: clock,
|
||||
db: db,
|
||||
chargeMeter: cm,
|
||||
}
|
||||
|
||||
// create session
|
||||
me.EXPECT().TotalEnergy().Return(1.0, nil)
|
||||
lp.createSession()
|
||||
assert.NotNil(t, lp.session)
|
||||
|
||||
// start charging
|
||||
lp.updateSession(func(session *coredb.Session) {
|
||||
if session.Created.IsZero() {
|
||||
session.Created = lp.clock.Now()
|
||||
}
|
||||
})
|
||||
assert.Equal(t, clock.Now(), lp.session.Created)
|
||||
|
||||
// stop charging
|
||||
clock.Add(time.Hour)
|
||||
lp.chargedEnergy = 1.23 * 1e3 // Wh
|
||||
me.EXPECT().TotalEnergy().Return(1.0+lp.chargedEnergy/1e3, nil) // match chargedEnergy
|
||||
|
||||
lp.stopSession()
|
||||
assert.NotNil(t, lp.session)
|
||||
assert.Equal(t, lp.chargedEnergy/1e3, lp.session.ChargedEnergy)
|
||||
assert.Equal(t, clock.Now(), lp.session.Finished)
|
||||
|
||||
s, err := db.Sessions()
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, s, 1)
|
||||
t.Log(s)
|
||||
|
||||
// stop charging - 2nd leg
|
||||
clock.Add(time.Hour)
|
||||
lp.chargedEnergy *= 2
|
||||
me.EXPECT().TotalEnergy().Return(3.0, nil) // doesn't match chargedEnergy
|
||||
|
||||
lp.stopSession()
|
||||
assert.NotNil(t, lp.session)
|
||||
assert.Equal(t, 3.0-1.0, lp.session.ChargedEnergy) // expect actual meter energy delta
|
||||
assert.Equal(t, clock.Now(), lp.session.Finished)
|
||||
|
||||
s, err = db.Sessions()
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, s, 1)
|
||||
t.Log(s)
|
||||
}
|
||||
15
core/site.go
15
core/site.go
|
|
@ -110,21 +110,6 @@ func NewSiteFromConfig(
|
|||
site.coordinator = coordinator.New(log, vehicles)
|
||||
site.savings = NewSavings(tariffs)
|
||||
|
||||
// migrate session log
|
||||
if serverdb.Instance != nil {
|
||||
var err error
|
||||
// TODO deprecate
|
||||
if table := "transactions"; serverdb.Instance.Migrator().HasTable(table) {
|
||||
err = serverdb.Instance.Migrator().RenameTable(table, new(db.Session))
|
||||
}
|
||||
if err == nil {
|
||||
err = serverdb.Instance.AutoMigrate(new(db.Session))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// upload telemetry on shutdown
|
||||
if telemetry.Enabled() {
|
||||
shutdown.Register(func() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue