Remove guard timer but keep charger sync logic (#12084)
This commit is contained in:
parent
75fcac5e7a
commit
d25af7d2be
23 changed files with 19 additions and 267 deletions
|
|
@ -182,8 +182,6 @@ export default {
|
|||
phaseRemaining: Number,
|
||||
pvRemaining: Number,
|
||||
pvAction: String,
|
||||
guardRemaining: Number,
|
||||
guardAction: String,
|
||||
smartCostLimit: Number,
|
||||
smartCostType: String,
|
||||
smartCostActive: Boolean,
|
||||
|
|
@ -196,7 +194,6 @@ export default {
|
|||
tickerHandler: null,
|
||||
phaseRemainingInterpolated: this.phaseRemaining,
|
||||
pvRemainingInterpolated: this.pvRemaining,
|
||||
guardRemainingInterpolated: this.guardRemaining,
|
||||
chargeDurationInterpolated: this.chargeDuration,
|
||||
chargeRemainingDurationInterpolated: this.chargeRemainingDuration,
|
||||
};
|
||||
|
|
@ -252,9 +249,6 @@ export default {
|
|||
pvRemaining() {
|
||||
this.pvRemainingInterpolated = this.pvRemaining;
|
||||
},
|
||||
guardRemaining() {
|
||||
this.guardRemainingInterpolated = this.guardRemaining;
|
||||
},
|
||||
chargeDuration() {
|
||||
this.chargeDurationInterpolated = this.chargeDuration;
|
||||
},
|
||||
|
|
@ -276,9 +270,6 @@ export default {
|
|||
if (this.pvRemainingInterpolated > 0) {
|
||||
this.pvRemainingInterpolated--;
|
||||
}
|
||||
if (this.guardRemainingInterpolated > 0) {
|
||||
this.guardRemainingInterpolated--;
|
||||
}
|
||||
if (this.chargeDurationInterpolated > 0 && this.charging) {
|
||||
this.chargeDurationInterpolated++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,9 +108,6 @@ const hoursFromNow = function (hours) {
|
|||
:pvRemainingInterpolated="155"
|
||||
/>
|
||||
</Variant>
|
||||
<Variant title="guard timer">
|
||||
<Vehicle v-bind="state" guardAction="enable" :guardRemainingInterpolated="123" />
|
||||
</Variant>
|
||||
<Variant title="vehicle switch">
|
||||
<Vehicle
|
||||
v-bind="state"
|
||||
|
|
|
|||
|
|
@ -95,8 +95,6 @@ export default {
|
|||
effectivePlanSoc: Number,
|
||||
effectivePlanTime: String,
|
||||
enabled: Boolean,
|
||||
guardAction: String,
|
||||
guardRemainingInterpolated: Number,
|
||||
heating: Boolean,
|
||||
id: [String, Number],
|
||||
integratedDevice: Boolean,
|
||||
|
|
|
|||
|
|
@ -144,43 +144,6 @@ describe("timer", () => {
|
|||
{ remaining: "1:30\u202Fm" }
|
||||
);
|
||||
});
|
||||
test("show guard timer if it exists", () => {
|
||||
expectStatus(
|
||||
{
|
||||
connected: true,
|
||||
guardAction: "enable",
|
||||
guardRemainingInterpolated: 90,
|
||||
},
|
||||
"guard",
|
||||
{ remaining: "1:30\u202Fm" }
|
||||
);
|
||||
});
|
||||
test("don't show guard timer if another timer exists", () => {
|
||||
expectStatus(
|
||||
{
|
||||
connected: true,
|
||||
charging: true,
|
||||
pvAction: "disable",
|
||||
pvRemainingInterpolated: 30,
|
||||
guardAction: "enable",
|
||||
guardRemainingInterpolated: 90,
|
||||
},
|
||||
"pvDisable",
|
||||
{ remaining: "30\u202Fs" }
|
||||
);
|
||||
});
|
||||
test("show guard timer if charging and no other timer exists", () => {
|
||||
expectStatus(
|
||||
{
|
||||
connected: true,
|
||||
charging: true,
|
||||
guardAction: "enable",
|
||||
guardRemainingInterpolated: 90,
|
||||
},
|
||||
"guard",
|
||||
{ remaining: "1:30\u202Fm" }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("vehicle target soc", () => {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ export default {
|
|||
phaseRemainingInterpolated: Number,
|
||||
pvAction: String,
|
||||
pvRemainingInterpolated: Number,
|
||||
guardAction: String,
|
||||
guardRemainingInterpolated: Number,
|
||||
targetChargeDisabled: Boolean,
|
||||
vehicleClimaterActive: Boolean,
|
||||
smartCostLimit: Number,
|
||||
|
|
@ -48,9 +46,6 @@ export default {
|
|||
this.pvRemainingInterpolated > 0 && ["enable", "disable"].includes(this.pvAction)
|
||||
);
|
||||
},
|
||||
guardTimerActive() {
|
||||
return this.guardRemainingInterpolated > 0 && this.guardAction === "enable";
|
||||
},
|
||||
message: function () {
|
||||
const t = (key, data) => {
|
||||
if (this.heating) {
|
||||
|
|
@ -128,12 +123,6 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
if (this.guardTimerActive) {
|
||||
return t("guard", {
|
||||
remaining: this.fmtDuration(this.guardRemainingInterpolated),
|
||||
});
|
||||
}
|
||||
|
||||
if (this.charging) {
|
||||
return t("charging");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@ const (
|
|||
pvEnable = "enable"
|
||||
pvDisable = "disable"
|
||||
|
||||
guardTimer = "guard"
|
||||
guardEnable = "enable"
|
||||
|
||||
phaseTimer = "phase"
|
||||
phaseScale1p = "scale1p"
|
||||
phaseScale3p = "scale3p"
|
||||
|
|
@ -55,9 +52,8 @@ const (
|
|||
minActiveCurrent = 1.0 // minimum current at which a phase is treated as active
|
||||
minActiveVoltage = 207 // minimum voltage at which a phase is treated as active
|
||||
|
||||
guardGracePeriod = 60 * time.Second // allow out of sync during this timespan
|
||||
phaseSwitchCommandTimeout = 30 * time.Second // do not sync charger enabled/disabled state during this timespan
|
||||
phaseSwitchDuration = 60 * time.Second // do not measure phases during this timespan
|
||||
chargerSwitchDuration = 60 * time.Second // allow out of sync during this timespan
|
||||
phaseSwitchDuration = 60 * time.Second // allow out of sync and do not measure phases during this timespan
|
||||
)
|
||||
|
||||
// elapsed is the time an expired timer will be set to
|
||||
|
|
@ -116,12 +112,12 @@ type Loadpoint struct {
|
|||
MeterRef string `mapstructure:"meter"` // Charge meter reference
|
||||
Soc SocConfig
|
||||
Enable, Disable ThresholdConfig
|
||||
GuardDuration time.Duration // charger enable/disable minimum holding time
|
||||
|
||||
// TODO deprecated
|
||||
ConfiguredPhases_ int `mapstructure:"phases"`
|
||||
MinCurrent_ float64 `mapstructure:"minCurrent"`
|
||||
MaxCurrent_ float64 `mapstructure:"maxCurrent"`
|
||||
GuardDuration_ time.Duration `mapstructure:"guardduration"` // charger enable/disable minimum holding time
|
||||
ConfiguredPhases_ int `mapstructure:"phases"`
|
||||
MinCurrent_ float64 `mapstructure:"minCurrent"`
|
||||
MaxCurrent_ float64 `mapstructure:"maxCurrent"`
|
||||
|
||||
minCurrent float64 // PV mode: start current Min+PV mode: min current
|
||||
maxCurrent float64 // Max allowed current. Physically ensured by the charger
|
||||
|
|
@ -134,9 +130,9 @@ type Loadpoint struct {
|
|||
phases int // Charger enabled phases, guarded by mutex
|
||||
measuredPhases int // Charger physically measured phases
|
||||
chargeCurrent float64 // Charger current limit
|
||||
guardUpdated time.Time // Charger enabled/disabled timestamp
|
||||
socUpdated time.Time // Soc updated timestamp (poll: connected)
|
||||
vehicleDetect time.Time // Vehicle connected timestamp
|
||||
chargerSwitched time.Time // Charger enabled/disabled timestamp
|
||||
phasesSwitched time.Time // Phase switch timestamp
|
||||
vehicleDetectTicker *clock.Ticker
|
||||
vehicleIdentifier string
|
||||
|
|
@ -295,7 +291,6 @@ func NewLoadpoint(log *util.Logger, settings *Settings) *Loadpoint {
|
|||
},
|
||||
Enable: ThresholdConfig{Delay: time.Minute, Threshold: 0}, // t, W
|
||||
Disable: ThresholdConfig{Delay: 3 * time.Minute, Threshold: 0}, // t, W
|
||||
GuardDuration: 5 * time.Minute,
|
||||
sessionEnergy: NewEnergyMetrics(),
|
||||
progress: NewProgress(0, 10), // soc progress indicator
|
||||
coordinator: coordinator.NewDummy(), // dummy vehicle coordinator
|
||||
|
|
@ -600,7 +595,6 @@ func (lp *Loadpoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even
|
|||
lp.publish(keys.PhasesActive, lp.ActivePhases())
|
||||
lp.publishTimer(phaseTimer, 0, timerInactive)
|
||||
lp.publishTimer(pvTimer, 0, timerInactive)
|
||||
lp.publishTimer(guardTimer, 0, timerInactive)
|
||||
|
||||
if phases := lp.getChargerPhysicalPhases(); phases != 0 {
|
||||
lp.publish(keys.ChargerPhysicalPhases, phases)
|
||||
|
|
@ -641,7 +635,6 @@ func (lp *Loadpoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even
|
|||
// read initial charger state to prevent immediately disabling charger
|
||||
if enabled, err := lp.charger.Enabled(); err == nil {
|
||||
if lp.enabled = enabled; enabled {
|
||||
lp.guardUpdated = lp.clock.Now()
|
||||
// set defined current for use by pv mode
|
||||
_ = lp.setLimit(lp.effectiveMinCurrent(), false)
|
||||
}
|
||||
|
|
@ -662,7 +655,7 @@ func (lp *Loadpoint) syncCharger() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if lp.guardGracePeriodElapsed() {
|
||||
if lp.chargerUpdateCompleted() {
|
||||
defer func() {
|
||||
lp.enabled = enabled
|
||||
lp.publish(keys.Enabled, lp.enabled)
|
||||
|
|
@ -672,11 +665,10 @@ func (lp *Loadpoint) syncCharger() error {
|
|||
if !enabled && lp.charging() {
|
||||
lp.log.WARN.Println("charger logic error: disabled but charging")
|
||||
enabled = true // treat as enabled when charging
|
||||
if lp.guardGracePeriodElapsed() {
|
||||
if lp.chargerUpdateCompleted() {
|
||||
if err := lp.charger.Enable(true); err != nil { // also enable charger to correct internal state
|
||||
return err
|
||||
}
|
||||
lp.elapseGuard()
|
||||
lp.elapsePVTimer()
|
||||
return nil
|
||||
}
|
||||
|
|
@ -693,10 +685,9 @@ func (lp *Loadpoint) syncCharger() error {
|
|||
|
||||
// smallest adjustment most PWM-Controllers can do is: 100%÷256×0,6A = 0.234A
|
||||
if math.Abs(lp.chargeCurrent-current) > 0.23 {
|
||||
if lp.guardGracePeriodElapsed() {
|
||||
if lp.chargerUpdateCompleted() {
|
||||
lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA, expected %.3gA)", current, lp.chargeCurrent)
|
||||
}
|
||||
|
||||
lp.chargeCurrent = current
|
||||
lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
|
||||
}
|
||||
|
|
@ -705,13 +696,9 @@ func (lp *Loadpoint) syncCharger() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if enabled || lp.phaseSwitchCommandTimeoutElapsed() {
|
||||
// ignore disabled state if vehicle was disconnected ^(lp.enabled && ^lp.connected)
|
||||
if lp.guardGracePeriodElapsed() && lp.phaseSwitchCompleted() && (enabled || lp.connected()) {
|
||||
lp.log.WARN.Printf("charger out of sync: expected %vd, got %vd", status[lp.enabled], status[enabled])
|
||||
lp.elapseGuard()
|
||||
}
|
||||
return nil
|
||||
// ignore disabled state if vehicle was disconnected ^(lp.enabled && ^lp.connected)
|
||||
if lp.chargerUpdateCompleted() && lp.phaseSwitchCompleted() && (enabled || lp.connected()) {
|
||||
lp.log.WARN.Printf("charger out of sync: expected %vd, got %vd", status[lp.enabled], status[enabled])
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -752,12 +739,6 @@ func (lp *Loadpoint) setLimit(chargeCurrent float64, force bool) error {
|
|||
lp.bus.Publish(evChargeCurrent, chargeCurrent)
|
||||
}
|
||||
|
||||
if lp.clock.Since(lp.guardUpdated).Truncate(time.Second) < lp.GuardDuration && !force {
|
||||
lp.publishTimer(guardTimer, lp.GuardDuration, guardEnable)
|
||||
return nil
|
||||
}
|
||||
lp.elapseGuard()
|
||||
|
||||
// set enabled/disabled
|
||||
if enabled := chargeCurrent >= lp.effectiveMinCurrent(); enabled != lp.enabled {
|
||||
if err := lp.charger.Enable(enabled); err != nil {
|
||||
|
|
@ -777,7 +758,7 @@ func (lp *Loadpoint) setLimit(chargeCurrent float64, force bool) error {
|
|||
lp.log.DEBUG.Printf("charger %s", status[enabled])
|
||||
lp.enabled = enabled
|
||||
lp.publish(keys.Enabled, lp.enabled)
|
||||
lp.guardUpdated = lp.clock.Now()
|
||||
lp.chargerSwitched = lp.clock.Now()
|
||||
|
||||
lp.bus.Publish(evChargeCurrent, chargeCurrent)
|
||||
|
||||
|
|
@ -968,8 +949,6 @@ func (lp *Loadpoint) elapsePVTimer() {
|
|||
|
||||
lp.pvTimer = elapsed
|
||||
lp.publishTimer(pvTimer, 0, timerInactive)
|
||||
|
||||
lp.elapseGuard()
|
||||
}
|
||||
|
||||
// resetPVTimer resets the pv enable/disable timer to disabled state
|
||||
|
|
@ -1061,7 +1040,7 @@ func (lp *Loadpoint) pvScalePhases(sitePower, minCurrent, maxCurrent float64) bo
|
|||
// - https://github.com/evcc-io/evcc/issues/2613
|
||||
measuredPhases := lp.getMeasuredPhases()
|
||||
if phases > 0 && phases < measuredPhases {
|
||||
if lp.guardGracePeriodElapsed() {
|
||||
if lp.chargerUpdateCompleted() {
|
||||
lp.log.WARN.Printf("ignoring inconsistent phases: %dp < %dp observed active", phases, measuredPhases)
|
||||
}
|
||||
lp.resetMeasuredPhases()
|
||||
|
|
@ -1140,9 +1119,6 @@ func (lp *Loadpoint) publishTimer(name string, delay time.Duration, action strin
|
|||
if name == phaseTimer {
|
||||
timer = lp.phaseTimer
|
||||
}
|
||||
if name == guardTimer {
|
||||
timer = lp.guardUpdated
|
||||
}
|
||||
|
||||
remaining := delay - lp.clock.Since(timer)
|
||||
if remaining < 0 {
|
||||
|
|
@ -1472,14 +1448,6 @@ func (lp *Loadpoint) publishSocAndRange() {
|
|||
}
|
||||
}
|
||||
|
||||
func (lp *Loadpoint) elapseGuard() {
|
||||
if lp.guardUpdated != elapsed {
|
||||
lp.log.DEBUG.Print("charger: guard elapse")
|
||||
lp.guardUpdated = elapsed
|
||||
lp.publishTimer(guardTimer, 0, timerInactive)
|
||||
}
|
||||
}
|
||||
|
||||
// addTask adds a single task to the queue
|
||||
func (lp *Loadpoint) addTask(task func()) {
|
||||
// test guard
|
||||
|
|
@ -1515,17 +1483,12 @@ func (lp *Loadpoint) stopWakeUpTimer() {
|
|||
lp.wakeUpTimer.Stop()
|
||||
}
|
||||
|
||||
// guardGracePeriodElapsed checks if last guard update is within guard grace period
|
||||
func (lp *Loadpoint) guardGracePeriodElapsed() bool {
|
||||
return time.Since(lp.guardUpdated) > guardGracePeriod
|
||||
// chargerUpdateCompleted returns true if enable command should be already processed by the charger (so we can try to sync charger and loadpoint)
|
||||
func (lp *Loadpoint) chargerUpdateCompleted() bool {
|
||||
return time.Since(lp.chargerSwitched) > chargerSwitchDuration
|
||||
}
|
||||
|
||||
// phaseSwitchCommandTimeoutElapsed returns true if phase switch command should be already processed by the charger
|
||||
func (lp *Loadpoint) phaseSwitchCommandTimeoutElapsed() bool {
|
||||
return time.Since(lp.phasesSwitched) > phaseSwitchCommandTimeout
|
||||
}
|
||||
|
||||
// phaseSwitchCompleted returns true if phase switch has completed
|
||||
// phaseSwitchCompleted returns true if phase switch command should be already processed by the charger (so we can try to sync charger and loadpoint and are able to measure currents)
|
||||
func (lp *Loadpoint) phaseSwitchCompleted() bool {
|
||||
return time.Since(lp.phasesSwitched) > phaseSwitchDuration
|
||||
}
|
||||
|
|
|
|||
|
|
@ -696,131 +696,6 @@ func TestSocPoll(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// test guard timer is properly published during disable cycle
|
||||
func TestGuardPublish(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
clock := clock.NewMock()
|
||||
charger := api.NewMockCharger(ctrl)
|
||||
rater := api.NewMockChargeRater(ctrl)
|
||||
startPointInTime := clock.Now()
|
||||
|
||||
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
|
||||
guardUpdated: startPointInTime,
|
||||
pvTimer: time.Time{},
|
||||
wakeUpTimer: NewTimer(),
|
||||
sessionEnergy: NewEnergyMetrics(),
|
||||
minCurrent: minA,
|
||||
maxCurrent: maxA,
|
||||
chargeCurrent: maxA,
|
||||
status: api.StatusC,
|
||||
mode: api.ModePV,
|
||||
enabled: true,
|
||||
Disable: ThresholdConfig{Delay: 2 * time.Minute, Threshold: 0}, // t, W
|
||||
GuardDuration: 3 * time.Minute,
|
||||
}
|
||||
|
||||
util.LogLevel("DEBUG", nil)
|
||||
|
||||
attachListeners(t, lp)
|
||||
// attach cache for verifying values
|
||||
_, expectCache := cacheExpecter(t, lp)
|
||||
|
||||
rater.EXPECT().ChargedEnergy().AnyTimes()
|
||||
charger.EXPECT().Enabled().DoAndReturn(func() (bool, error) { return lp.enabled, nil }).AnyTimes() // just follow the loadpoint
|
||||
charger.EXPECT().Status().Return(api.StatusC, nil).Times(4)
|
||||
charger.EXPECT().Enable(false).Return(nil)
|
||||
|
||||
tc := []struct {
|
||||
step string
|
||||
guardUpdates time.Time
|
||||
guardTimerRemaining time.Duration
|
||||
}{
|
||||
{"kick off pv disable timer", startPointInTime, 3 * time.Minute},
|
||||
{"continue pv disable timer", startPointInTime, 2 * time.Minute},
|
||||
{"disable charger prevented by guard", startPointInTime, 1 * time.Minute},
|
||||
{"guard elapse, publish new guard time", startPointInTime.Add(3 * time.Minute), time.Duration(0)},
|
||||
}
|
||||
|
||||
for _, tc := range tc {
|
||||
t.Logf("%+v", tc)
|
||||
lp.Update(15000, false, false, false, 0, nil, nil)
|
||||
assert.Equal(t, tc.guardUpdates, lp.guardUpdated)
|
||||
expectCache(guardTimer+"Remaining", tc.guardTimerRemaining)
|
||||
clock.Add(time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
// test guard timer is properly published if charger disable sequence is aborted
|
||||
func TestGuardPublishOnDisableAbort(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
clock := clock.NewMock()
|
||||
charger := api.NewMockCharger(ctrl)
|
||||
rater := api.NewMockChargeRater(ctrl)
|
||||
startPointInTime := clock.Now()
|
||||
|
||||
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
|
||||
guardUpdated: startPointInTime,
|
||||
pvTimer: time.Time{},
|
||||
wakeUpTimer: NewTimer(),
|
||||
sessionEnergy: NewEnergyMetrics(),
|
||||
minCurrent: minA,
|
||||
maxCurrent: maxA,
|
||||
chargeCurrent: maxA,
|
||||
status: api.StatusC,
|
||||
mode: api.ModePV,
|
||||
enabled: true,
|
||||
Disable: ThresholdConfig{Delay: 2 * time.Minute, Threshold: 0}, // t, W
|
||||
GuardDuration: 4 * time.Minute,
|
||||
}
|
||||
|
||||
util.LogLevel("DEBUG", nil)
|
||||
|
||||
attachListeners(t, lp)
|
||||
// attach cache for verifying values
|
||||
_, expectCache := cacheExpecter(t, lp)
|
||||
|
||||
rater.EXPECT().ChargedEnergy().AnyTimes()
|
||||
charger.EXPECT().Enabled().DoAndReturn(func() (bool, error) { return lp.enabled, nil }).AnyTimes() // just follow the loadpoint
|
||||
charger.EXPECT().Status().Return(api.StatusC, nil).Times(5)
|
||||
|
||||
tc := []struct {
|
||||
step string
|
||||
sitePower float64
|
||||
guardUpdated time.Time
|
||||
guardTimerRemaining time.Duration
|
||||
}{
|
||||
{"kick off pv disable timer", 15000, startPointInTime, 4 * time.Minute},
|
||||
{"continue pv disable timer", 15000, startPointInTime, 3 * time.Minute},
|
||||
{"disable charger prevented by guard", 15000, startPointInTime, 2 * time.Minute},
|
||||
{"disable charger reset, pv power is back", -1, startPointInTime, 1 * time.Minute},
|
||||
{"guard elapsed, publish new guard time", -1, elapsed, time.Duration(0)},
|
||||
}
|
||||
|
||||
for _, tc := range tc {
|
||||
t.Logf("%+v", tc)
|
||||
lp.Update(tc.sitePower, false, false, false, 0, nil, nil)
|
||||
assert.Equal(t, tc.guardUpdated, lp.guardUpdated)
|
||||
expectCache(guardTimer+"Remaining", tc.guardTimerRemaining)
|
||||
clock.Add(time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
// test PV hysteresis after phase switch down, depending on remaining energy
|
||||
func TestPVHysteresisAfterPhaseSwitch(t *testing.T) {
|
||||
const dt = time.Minute
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ loadpoints:
|
|||
disable: # pv mode disable behavior
|
||||
delay: 3m # threshold must be exceeded for this long
|
||||
threshold: 0 # maximum import power (W)
|
||||
guardDuration: 5m # switch charger contactor not more often than this (default 5m)
|
||||
|
||||
# tariffs are the fixed or variable tariffs
|
||||
tariffs:
|
||||
|
|
|
|||
|
|
@ -241,7 +241,6 @@ cleanEnergyCharging = "Energia neta disponible. Carregant..."
|
|||
climating = "Precondicionament detectat."
|
||||
connected = "Connectat."
|
||||
disconnected = "Desconnectat."
|
||||
guard = "Protecció de commutació activa durant {remaining}"
|
||||
minCharge = "Càrrega mínima fins a {soc}%."
|
||||
pvDisable = "Excedent insuficient. Pausa en {remaining}..."
|
||||
pvEnable = "Excedent disponible. Començar en {remaining}..."
|
||||
|
|
|
|||
|
|
@ -370,7 +370,6 @@ cleanEnergyCharging = "Oplader med CO2 neutral energi: {co2} (limit {limit})"
|
|||
climating = "Forkonditionering registreret."
|
||||
connected = "Forbundet."
|
||||
disconnected = "Afbrudt."
|
||||
guard = "Switching-beskyttelse er aktiv i {remaining}…"
|
||||
minCharge = "Minimum opladning til {soc} %."
|
||||
pvDisable = "Ikke nok overskud. Pause i {remaining}..."
|
||||
pvEnable = "Overskud tilgængeligt. Starter om {remaining}..."
|
||||
|
|
|
|||
|
|
@ -362,7 +362,6 @@ cleanEnergyCharging = "Lade saubere Energie: {co2} (Grenze {limit})"
|
|||
climating = "Vorklimatisierung erkannt."
|
||||
connected = "Verbunden."
|
||||
disconnected = "Nicht verbunden."
|
||||
guard = "Schaltschutz aktiv für {remaining}."
|
||||
minCharge = "Mindestladung bis {soc}%."
|
||||
pvDisable = "Zu wenig Überschuss. Pausiere in {remaining} …"
|
||||
pvEnable = "Überschuss verfügbar. Starte in {remaining} …"
|
||||
|
|
|
|||
|
|
@ -359,7 +359,6 @@ cleanEnergyCharging = "Charging clean energy: {co2} (limit {limit})"
|
|||
climating = "Pre-conditioning detected."
|
||||
connected = "Connected."
|
||||
disconnected = "Disconnected."
|
||||
guard = "Switching protection active for {remaining}."
|
||||
minCharge = "Minimum charging to {soc}%."
|
||||
pvDisable = "Not enough surplus. Pausing in {remaining}…"
|
||||
pvEnable = "Surplus available. Starting in {remaining}…"
|
||||
|
|
|
|||
|
|
@ -375,9 +375,6 @@ cleanEnergyCharging = "Cargando con energía limpia: {co2} (límite {limit})"
|
|||
climating = "Preacondicionamiento detectado."
|
||||
connected = "Conectado."
|
||||
disconnected = "Desconectado."
|
||||
guard = "Cambiando la protección activa para {remaining}"
|
||||
guardDisable = "Pausando en {remaining}..."
|
||||
guardEnable = "Comenzando en {remaining}..."
|
||||
minCharge = "Carga mínima hasta {soc}%."
|
||||
pvDisable = "Excedente insuficiente. Pausa en {remaining}..."
|
||||
pvEnable = "Excedente disponibile. Empezar en {remaining}..."
|
||||
|
|
|
|||
|
|
@ -293,7 +293,6 @@ cleanEnergyCharging = "Lataa puhdasta energiaa: {co2} (limit {limit})"
|
|||
climating = "Esilämmitys/-viilennys havaittu."
|
||||
connected = "Yhdistetty."
|
||||
disconnected = "Irroitettu."
|
||||
guard = "Suojaus aktiivinen: {remaining}…"
|
||||
minCharge = "Ladataan minimissään {soc}%."
|
||||
pvDisable = "Ei tarpeeksi ylijäämää. Tauko {remaining}…"
|
||||
pvEnable = "Ylijäämää saatavilla. Aloitus {remaining}…"
|
||||
|
|
|
|||
|
|
@ -321,7 +321,6 @@ cleanEnergyCharging = "En charge avec énergie propre : {co2} (limit < {limit}
|
|||
climating = "Pré-conditionnement détecté."
|
||||
connected = "Connecté."
|
||||
disconnected = "Déconnecté."
|
||||
guard = "Protection de commutation active pour {remaining}..."
|
||||
minCharge = "Charge minimale jusqu'à {soc}%."
|
||||
pvDisable = "Pas assez de surplus. Pause dans {remaining}…"
|
||||
pvEnable = "Surplus disponible. Démarre dans {remaining}…"
|
||||
|
|
|
|||
|
|
@ -323,7 +323,6 @@ cleanEnergyCharging = "Napajanje čistom energijom: {co2} (ograničenje {limit})
|
|||
climating = "Otkriveno predkondicioniranje."
|
||||
connected = "Povezano."
|
||||
disconnected = "Nepovezano."
|
||||
guard = "Promjena zaštite aktivna za {remaining}."
|
||||
minCharge = "Minimalno napajanje do {soc} %."
|
||||
pvDisable = "Nema dovoljno viška. Zaustavlja se za {remaining} …"
|
||||
pvEnable = "Dostupan je višak. Počinje za {remaining} …"
|
||||
|
|
|
|||
|
|
@ -375,9 +375,6 @@ cleanEnergyCharging = "Įkraunama švaria energija: {co2} (limitas {limit})"
|
|||
climating = "Aptiktas išankstinis kondicionavimas."
|
||||
connected = "Prijungtas."
|
||||
disconnected = "Neprijungtas."
|
||||
guard = "Per dažno junginėjimo apsauga {remaining}…"
|
||||
guardDisable = "Pauzė už {remaining}…"
|
||||
guardEnable = "Pradedam už {remaining}…"
|
||||
minCharge = "Minimalus įkrovimas iki {soc}%."
|
||||
pvDisable = "Trūksta saulės. Pauzė už {remaining}..."
|
||||
pvEnable = "Saulės užtenka, įkrovimas už {remaining}..."
|
||||
|
|
|
|||
|
|
@ -372,7 +372,6 @@ cleanEnergyCharging = "Laden actief met schone energie. {co2} (limit {limit})"
|
|||
climating = "Voor-conditionering gedetecteerd."
|
||||
connected = "Verbonden."
|
||||
disconnected = "Niet verbonden."
|
||||
guard = "Schakelbeveiliging actief voor {remaining}."
|
||||
minCharge = "Minimaal opladen naar {soc}%."
|
||||
pvDisable = "Onvoldoende PV overschot beschikbaar. Pauzeren over {remaining}..."
|
||||
pvEnable = "Voldoende PV overschot beschikbaar. Starten over {remaining}..."
|
||||
|
|
|
|||
|
|
@ -284,7 +284,6 @@ cleanEnergyCharging = "Ren energi tilgjengelig. Lader …"
|
|||
climating = "Klimaanlegg på forhånd oppdaget."
|
||||
connected = "Tilkoblet."
|
||||
disconnected = "Frakoblet."
|
||||
guard = "Bryterbeskyttelse aktiv i {remaining} …"
|
||||
minCharge = "Minimumslading til {soc}%."
|
||||
pvDisable = "Ikke nok overskudd. Pause i {remaining}..."
|
||||
pvEnable = "Overskudd tilgjengelig. Starter om {remaining}..."
|
||||
|
|
|
|||
|
|
@ -322,7 +322,6 @@ cleanEnergyCharging = "Ładowanie czystą energią: {co2} (ograniczenie {limit})
|
|||
climating = "Wykryto wstępne przygotowanie"
|
||||
connected = "Połączony."
|
||||
disconnected = "Rozłączony."
|
||||
guard = "Ochrona przełączania aktywna {remaining}…"
|
||||
minCharge = "Minimalne ładowanie do {soc}%."
|
||||
pvDisable = "Za mało nadwyżki. Pauza po {remaining}..."
|
||||
pvEnable = "Dostępna nadwyżka. Począwszy po {remaining}..."
|
||||
|
|
|
|||
|
|
@ -323,9 +323,6 @@ cleanEnergyCharging = "Carregando energia limpa: {co2} (limit {limit})"
|
|||
climating = "Pré-condicionamento detectado."
|
||||
connected = "Ligado."
|
||||
disconnected = "Não conectado."
|
||||
guard = "Proteção de ligação ativa para {remaining}."
|
||||
guardDisable = "Pausar em {remaining}…"
|
||||
guardEnable = "Iniciando em {remaining}..."
|
||||
minCharge = "Carga mínima até {soc}%"
|
||||
pvDisable = "Excesso insuficiente. Pausa em {remaining}..."
|
||||
pvEnable = "Excesso disponível. Carga em {remaining}..."
|
||||
|
|
|
|||
|
|
@ -370,7 +370,6 @@ cleanEnergyCharging = "Laddar grön energi: {co2} (gräns {limit})"
|
|||
climating = "Förvärmning identifierad."
|
||||
connected = "Inkopplad."
|
||||
disconnected = "Frånkopplad."
|
||||
guard = "Brytarskydd aktivt i {remaining}…"
|
||||
minCharge = "Minimiladdning till {soc}%."
|
||||
pvDisable = "Inte tillräckligt med överskott. Pausar i {remaining}..."
|
||||
pvEnable = "Överskott tillgängligt. Börjar om {remaining}..."
|
||||
|
|
|
|||
|
|
@ -281,9 +281,6 @@ cleanEnergyCharging = "Чиста енергія доступна. Зарядж
|
|||
climating = "Виявлено попередню підготовку."
|
||||
connected = "Підключено."
|
||||
disconnected = "Відключено."
|
||||
guard = "Захист від перемикання активовано для {remaining}."
|
||||
guardDisable = "Пауза через {remaining}…"
|
||||
guardEnable = "Початок через {remaining}…"
|
||||
minCharge = "Мінімальна зарядка до {soc}%."
|
||||
pvDisable = "Недостатньо надлишку. Пауза через {remaining}…"
|
||||
pvEnable = "Надлишок доступний. Початок через {remaining}…"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue