Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions server/http_loadpoint_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
"errors"
"fmt"
"net/http"
"slices"
"strconv"
"strings"
"time"

"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/planner"
"github.com/evcc-io/evcc/core/site"
"github.com/evcc-io/evcc/util"
"github.com/gorilla/mux"
"github.com/samber/lo"
)

type PlanResponse struct {
Expand All @@ -32,6 +35,71 @@
Power float64 `json:"power"`
}

// metaPlanHandler returns the current plan
func metaPlanHandler(site site.API) http.HandlerFunc {

Check failure on line 39 in server/http_loadpoint_handler.go

View workflow job for this annotation

GitHub Actions / Lint

func metaPlanHandler is unused (unused)
return func(w http.ResponseWriter, r *http.Request) {
var res struct {
MetaPlan PlanPreviewResponse `json:"metaPlan"`
Loadpoints []PlanResponse `json:"loadpoints"`
}

var totalDuration time.Duration

for _, lp := range site.Loadpoints() {
maxPower := lp.EffectiveMaxPower()
planTime := lp.EffectivePlanTime()
id := lp.EffectivePlanId()

goal, _ := lp.GetPlanGoal()
requiredDuration := lp.GetPlanRequiredDuration(goal, maxPower)

res.Loadpoints = append(res.Loadpoints, PlanResponse{
PlanId: id,
PlanTime: planTime,
Duration: int64(requiredDuration.Seconds()),
Power: maxPower,
})

totalDuration += requiredDuration
}

latestEnd := lo.MinBy(res.Loadpoints, func(a, b PlanResponse) bool {
return a.PlanTime.Before(b.PlanTime)
}).PlanTime

for i := 0; i < len(res.Loadpoints); i++ {
for j := i + 1; j < len(res.Loadpoints); j++ {
lpi := res.Loadpoints[i]
lpj := res.Loadpoints[j]

maxStart := slices.MaxFunc([]time.Time{
lpi.PlanTime.Add(-time.Duration(lpi.Duration) * time.Second),
lpj.PlanTime.Add(-time.Duration(lpj.Duration) * time.Second)},
time.Time.Compare)
minEnd := slices.MinFunc([]time.Time{lpi.PlanTime, lpj.PlanTime}, time.Time.Compare)

// add overlapping ranges to total require duration
if d := minEnd.Sub(maxStart); d > 0 {
totalDuration += d
}
}
}

tariff := site.GetTariff(api.TariffUsagePlanner)
planner := planner.New(util.NewLogger("meta-plan"), tariff)

metaPlan := planner.Plan(totalDuration, 0, latestEnd)

res.MetaPlan = PlanPreviewResponse{
PlanTime: latestEnd,
Duration: int64(totalDuration.Seconds()),
Plan: metaPlan,
}

jsonWrite(w, res)
}
}

// planHandler returns the current plan
func planHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
Expand Down
Loading