Heating: add daily session reset (#22068)
This commit is contained in:
parent
feba941091
commit
d91690e463
5 changed files with 140 additions and 8 deletions
|
|
@ -7,7 +7,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
//go:generate go tool mockgen -package api -destination mock.go github.com/evcc-io/evcc/api Charger,ChargeState,CurrentLimiter,CurrentGetter,PhaseSwitcher,PhaseGetter,Identifier,Meter,MeterEnergy,PhaseCurrents,Vehicle,ChargeRater,Battery,Tariff,BatteryController,Circuit
|
||||
//go:generate go tool mockgen -package api -destination mock.go github.com/evcc-io/evcc/api Charger,ChargeState,CurrentLimiter,CurrentGetter,PhaseSwitcher,PhaseGetter,FeatureDescriber,Identifier,Meter,MeterEnergy,PhaseCurrents,Vehicle,ChargeRater,Battery,Tariff,BatteryController,Circuit
|
||||
|
||||
// Meter provides total active power in W
|
||||
type Meter interface {
|
||||
|
|
|
|||
42
api/mock.go
42
api/mock.go
|
|
@ -1,9 +1,9 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/evcc-io/evcc/api (interfaces: Charger,ChargeState,CurrentLimiter,CurrentGetter,PhaseSwitcher,PhaseGetter,Identifier,Meter,MeterEnergy,PhaseCurrents,Vehicle,ChargeRater,Battery,Tariff,BatteryController,Circuit)
|
||||
// Source: github.com/evcc-io/evcc/api (interfaces: Charger,ChargeState,CurrentLimiter,CurrentGetter,PhaseSwitcher,PhaseGetter,FeatureDescriber,Identifier,Meter,MeterEnergy,PhaseCurrents,Vehicle,ChargeRater,Battery,Tariff,BatteryController,Circuit)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package api -destination mock.go github.com/evcc-io/evcc/api Charger,ChargeState,CurrentLimiter,CurrentGetter,PhaseSwitcher,PhaseGetter,Identifier,Meter,MeterEnergy,PhaseCurrents,Vehicle,ChargeRater,Battery,Tariff,BatteryController,Circuit
|
||||
// mockgen -package api -destination mock.go github.com/evcc-io/evcc/api Charger,ChargeState,CurrentLimiter,CurrentGetter,PhaseSwitcher,PhaseGetter,FeatureDescriber,Identifier,Meter,MeterEnergy,PhaseCurrents,Vehicle,ChargeRater,Battery,Tariff,BatteryController,Circuit
|
||||
//
|
||||
|
||||
// Package api is a generated GoMock package.
|
||||
|
|
@ -292,6 +292,44 @@ func (mr *MockPhaseGetterMockRecorder) GetPhases() *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhases", reflect.TypeOf((*MockPhaseGetter)(nil).GetPhases))
|
||||
}
|
||||
|
||||
// MockFeatureDescriber is a mock of FeatureDescriber interface.
|
||||
type MockFeatureDescriber struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockFeatureDescriberMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockFeatureDescriberMockRecorder is the mock recorder for MockFeatureDescriber.
|
||||
type MockFeatureDescriberMockRecorder struct {
|
||||
mock *MockFeatureDescriber
|
||||
}
|
||||
|
||||
// NewMockFeatureDescriber creates a new mock instance.
|
||||
func NewMockFeatureDescriber(ctrl *gomock.Controller) *MockFeatureDescriber {
|
||||
mock := &MockFeatureDescriber{ctrl: ctrl}
|
||||
mock.recorder = &MockFeatureDescriberMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockFeatureDescriber) EXPECT() *MockFeatureDescriberMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Features mocks base method.
|
||||
func (m *MockFeatureDescriber) Features() []Feature {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Features")
|
||||
ret0, _ := ret[0].([]Feature)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Features indicates an expected call of Features.
|
||||
func (mr *MockFeatureDescriberMockRecorder) Features() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Features", reflect.TypeOf((*MockFeatureDescriber)(nil).Features))
|
||||
}
|
||||
|
||||
// MockIdentifier is a mock of Identifier interface.
|
||||
type MockIdentifier struct {
|
||||
ctrl *gomock.Controller
|
||||
|
|
|
|||
|
|
@ -1820,6 +1820,8 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, rates api.Rate
|
|||
lp.publish(keys.Connected, lp.connected())
|
||||
lp.publish(keys.Charging, lp.charging())
|
||||
|
||||
lp.resetHeatingSession()
|
||||
|
||||
if sr, ok := lp.charger.(api.StatusReasoner); ok && lp.GetStatus() == api.StatusB {
|
||||
if r, err := sr.StatusReason(); err == nil {
|
||||
lp.publish(keys.ChargerStatusReason, r)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package core
|
|||
import (
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/core/session"
|
||||
"github.com/jinzhu/now"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
|
|
@ -106,3 +107,17 @@ func (lp *Loadpoint) clearSession() {
|
|||
|
||||
lp.session = nil
|
||||
}
|
||||
|
||||
func (lp *Loadpoint) resetHeatingSession() {
|
||||
if lp.session == nil || !lp.chargerHasFeature(api.Heating) || !lp.chargerHasFeature(api.IntegratedDevice) {
|
||||
return
|
||||
}
|
||||
|
||||
if !now.With(lp.clock.Now()).BeginningOfDay().After(lp.session.Created) {
|
||||
return
|
||||
}
|
||||
|
||||
lp.stopSession()
|
||||
lp.clearSession()
|
||||
lp.createSession()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ import (
|
|||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
func sessionStart(lp *Loadpoint) func(session *session.Session) {
|
||||
return func(session *session.Session) {
|
||||
if session.Created.IsZero() {
|
||||
session.Created = lp.clock.Now()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSession(t *testing.T) {
|
||||
var err error
|
||||
serverdb.Instance, err = serverdb.New("sqlite", ":memory:")
|
||||
|
|
@ -50,11 +58,7 @@ func TestSession(t *testing.T) {
|
|||
assert.NotNil(t, lp.session)
|
||||
|
||||
// start charging
|
||||
lp.updateSession(func(session *session.Session) {
|
||||
if session.Created.IsZero() {
|
||||
session.Created = lp.clock.Now()
|
||||
}
|
||||
})
|
||||
lp.updateSession(sessionStart(lp))
|
||||
assert.Equal(t, clock.Now(), lp.session.Created)
|
||||
|
||||
// stop charging
|
||||
|
|
@ -181,3 +185,76 @@ func createMockSessions(db *session.DB, clock *clock.Mock) []*session.Session {
|
|||
}
|
||||
return sessions
|
||||
}
|
||||
|
||||
func TestResetHeatingSession(t *testing.T) {
|
||||
var err error
|
||||
serverdb.Instance, err = serverdb.New("sqlite", ":memory:")
|
||||
require.NoError(t, err)
|
||||
|
||||
db, err := session.NewStore("foo", serverdb.Instance)
|
||||
require.NoError(t, err)
|
||||
|
||||
clock := clock.NewMock()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
cc := api.NewMockCharger(ctrl)
|
||||
fd := api.NewMockFeatureDescriber(ctrl)
|
||||
|
||||
type FeatureDecorator struct {
|
||||
api.Charger
|
||||
api.FeatureDescriber
|
||||
}
|
||||
|
||||
charger := &FeatureDecorator{Charger: cc, FeatureDescriber: fd}
|
||||
fd.EXPECT().Features().AnyTimes().Return([]api.Feature{
|
||||
api.Heating, api.IntegratedDevice,
|
||||
})
|
||||
|
||||
mm := api.NewMockMeter(ctrl)
|
||||
me := api.NewMockMeterEnergy(ctrl)
|
||||
|
||||
type EnergyDecorator struct {
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}
|
||||
|
||||
cm := &EnergyDecorator{Meter: mm, MeterEnergy: me}
|
||||
|
||||
lp := &Loadpoint{
|
||||
log: util.NewLogger("foo"),
|
||||
clock: clock,
|
||||
db: db,
|
||||
charger: charger,
|
||||
chargeMeter: cm,
|
||||
}
|
||||
|
||||
// create session
|
||||
me.EXPECT().TotalEnergy().Return(1.0, nil)
|
||||
lp.createSession()
|
||||
require.NotNil(t, lp.session)
|
||||
assert.True(t, lp.session.Created.IsZero())
|
||||
|
||||
// actually mark session as started
|
||||
lp.session.Created = clock.Now()
|
||||
assert.Equal(t, clock.Now(), lp.session.Created)
|
||||
|
||||
clock.Add(36 * time.Hour)
|
||||
me.EXPECT().TotalEnergy().Return(1.0, nil).MaxTimes(2)
|
||||
|
||||
lp.resetHeatingSession()
|
||||
require.NotNil(t, lp.session)
|
||||
assert.True(t, lp.session.Created.IsZero())
|
||||
|
||||
lp.updateSession(sessionStart(lp))
|
||||
assert.Equal(t, clock.Now(), lp.session.Created)
|
||||
|
||||
me.EXPECT().TotalEnergy().Return(3.0, nil)
|
||||
lp.stopSession()
|
||||
|
||||
assert.NotNil(t, lp.session)
|
||||
assert.Equal(t, clock.Now(), lp.session.Finished)
|
||||
assert.Equal(t, 1.0, *lp.session.MeterStart)
|
||||
assert.Equal(t, 3.0, *lp.session.MeterStop)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue