Optimizer: reduce interval to 15min (#29137)
This commit is contained in:
parent
467c3c572e
commit
f69252e672
6 changed files with 55 additions and 37 deletions
|
|
@ -1,9 +1,19 @@
|
|||
<template>
|
||||
<div class="container px-4 safe-area-inset">
|
||||
<TopHeader title="Optimize Debug" />
|
||||
<div class="alert alert-light mb-5">
|
||||
This page is for development purposes only. Gives insights into the upcoming
|
||||
optimization algorithm.
|
||||
<div class="alert alert-light mb-5 d-flex justify-content-between align-items-center">
|
||||
<span>
|
||||
This page is for development purposes only. Gives insights into the upcoming
|
||||
optimization algorithm.
|
||||
</span>
|
||||
<button
|
||||
class="btn btn-sm ms-3 text-nowrap"
|
||||
:class="optimizeCooldown ? 'btn-outline-secondary disabled' : 'btn-outline-dark'"
|
||||
:disabled="optimizeCooldown"
|
||||
@click="optimizeNow"
|
||||
>
|
||||
{{ optimizeCooldown ? "Requested" : "Optimize now" }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<main class="col-12">
|
||||
|
|
@ -133,6 +143,7 @@ import PriceChart from "../components/Optimize/PriceChart.vue";
|
|||
import TimeSeriesDataTable from "../components/Optimize/TimeSeriesDataTable.vue";
|
||||
import CopyButton from "../components/Optimize/CopyButton.vue";
|
||||
import { formatCompactJson } from "../components/Optimize/compactJson";
|
||||
import api from "../api";
|
||||
import store from "../store";
|
||||
import formatter from "../mixins/formatter";
|
||||
import colors from "../colors";
|
||||
|
|
@ -150,6 +161,11 @@ export default defineComponent({
|
|||
CopyButton,
|
||||
},
|
||||
mixins: [formatter],
|
||||
data() {
|
||||
return {
|
||||
optimizeCooldown: false,
|
||||
};
|
||||
},
|
||||
head() {
|
||||
return { title: "Optimize Debug" };
|
||||
},
|
||||
|
|
@ -191,7 +207,16 @@ export default defineComponent({
|
|||
return this.evopt?.res ? formatCompactJson(this.evopt.res) : "";
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
evopt() {
|
||||
this.optimizeCooldown = false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
optimizeNow() {
|
||||
api.post("optimize");
|
||||
this.optimizeCooldown = true;
|
||||
},
|
||||
dimColorBy25Percent(color: string): string {
|
||||
// Convert color to 25% opacity (40 in hex = 25% of 255)
|
||||
return color?.toLowerCase().replace(/ff$/, "40") || color;
|
||||
|
|
|
|||
|
|
@ -792,7 +792,7 @@ func (site *Site) updateMeters() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if sponsor.IsAuthorized() && optimizerEnabled() {
|
||||
if sponsor.IsAuthorized() && optimizerEnabled() && time.Since(optimizerUpdated) >= tariff.SlotDuration {
|
||||
go site.optimizerUpdateAsync()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type API interface {
|
|||
|
||||
Loadpoints() []loadpoint.API
|
||||
Vehicles() Vehicles
|
||||
Optimize() error
|
||||
|
||||
// Meta
|
||||
GetTitle() string
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/evcc-io/evcc/core/site"
|
||||
"github.com/evcc-io/evcc/server/db/settings"
|
||||
"github.com/evcc-io/evcc/util/config"
|
||||
"github.com/evcc-io/evcc/util/sponsor"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
|
|
@ -35,6 +36,16 @@ func filterConfigurable(ref []string) []string {
|
|||
})
|
||||
}
|
||||
|
||||
// Optimize updates the optimizer
|
||||
func (site *Site) Optimize() error {
|
||||
if !sponsor.IsAuthorized() || !optimizerEnabled() {
|
||||
return api.ErrNotAvailable
|
||||
}
|
||||
|
||||
go site.optimizerUpdateAsync()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle returns the title
|
||||
func (site *Site) GetTitle() string {
|
||||
site.RLock()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
|
|
@ -30,8 +30,8 @@ var (
|
|||
eta = float32(0.9) // efficiency of the battery charging/discharging
|
||||
batteryPower = float32(6000) // default power of the battery in W
|
||||
|
||||
updated time.Time
|
||||
mu atomic.Uint32
|
||||
mu sync.Mutex
|
||||
optimizerUpdated time.Time
|
||||
)
|
||||
|
||||
// optimizerResult wraps the optimizer publish payload to implement BytesMarshaler.
|
||||
|
|
@ -73,26 +73,6 @@ type batteryResult struct {
|
|||
Empty time.Time `json:"empty,omitzero"`
|
||||
}
|
||||
|
||||
// func (br batteryResult) MarshalJSON() ([]byte, error) {
|
||||
// var full, empty int64
|
||||
// if !br.Full.IsZero() {
|
||||
// full = int64(time.Until(br.Full).Seconds())
|
||||
// }
|
||||
// if !br.Empty.IsZero() {
|
||||
// empty = int64(time.Until(br.Empty).Seconds())
|
||||
// }
|
||||
|
||||
// return json.Marshal(struct {
|
||||
// batteryResult
|
||||
// UntilFull int64 `json:"untilFull,omitempty"`
|
||||
// UntilEmpty int64 `json:"untilEmpty,omitempty"`
|
||||
// }{
|
||||
// batteryResult: br,
|
||||
// UntilFull: full,
|
||||
// UntilEmpty: empty,
|
||||
// })
|
||||
// }
|
||||
|
||||
type requestDetails struct {
|
||||
Timestamps []time.Time `json:"timestamp"`
|
||||
BatteryDetails []batteryDetail `json:"batteryDetails"`
|
||||
|
|
@ -101,19 +81,19 @@ type requestDetails struct {
|
|||
const slotsPerHour = float64(time.Hour / tariff.SlotDuration)
|
||||
|
||||
func (site *Site) optimizerUpdateAsync() {
|
||||
if !mu.TryLock() {
|
||||
return
|
||||
}
|
||||
defer mu.Unlock()
|
||||
|
||||
if time.Since(optimizerUpdated) < 2*time.Minute {
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if time.Since(updated) < 2*time.Minute {
|
||||
return
|
||||
}
|
||||
|
||||
if !mu.CompareAndSwap(0, 1) {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
updated = time.Now()
|
||||
mu.Store(0)
|
||||
optimizerUpdated = time.Now()
|
||||
|
||||
if r := recover(); r != nil {
|
||||
err = fmt.Errorf("panic %v", r)
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ func (s *HTTPd) RegisterSiteHandlers(site site.API) {
|
|||
"deletesession": {"DELETE", "/session/{id:[0-9]+}", deleteSessionHandler},
|
||||
"gridsessions": {"GET", "/gridsessions", gridSessionsHandler},
|
||||
"energyhistory": {"GET", "/history/energy", energyHistoryHandler},
|
||||
"optimize": {"POST", "/optimize", getHandler(site.Optimize)},
|
||||
"telemetry2": {"POST", "/settings/telemetry/{value:[01truefalse]+}", boolHandler(telemetry.Enable, telemetry.Enabled)},
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue