Skip to content
Draft
Show file tree
Hide file tree
Changes from 14 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
31 changes: 30 additions & 1 deletion api/plans.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package api

import "time"
import (
"encoding/json"
"time"
)

type RepeatingPlan struct {
Weekdays []int `json:"weekdays"` // 0-6 (Sunday-Saturday)
Expand All @@ -15,3 +18,29 @@ type PlanStrategy struct {
Continuous bool `json:"continuous"` // force continuous planning
Precondition time.Duration `json:"precondition"` // precondition duration in seconds
}

type planStrategy struct {
Continuous bool `json:"continuous"` // force continuous planning
Precondition int64 `json:"precondition"` // precondition duration in seconds
}

func (ps PlanStrategy) MarshalJSON() ([]byte, error) {
return json.Marshal(planStrategy{
Continuous: ps.Continuous,
Precondition: int64(ps.Precondition.Seconds()),
})
}

func (ps *PlanStrategy) UnmarshalJSON(data []byte) error {
var res planStrategy
if err := json.Unmarshal(data, &res); err != nil {
return err
}

*ps = PlanStrategy{
Continuous: res.Continuous,
Precondition: time.Duration(res.Precondition) * time.Second,
}

return nil
}
3 changes: 1 addition & 2 deletions assets/js/components/ChargingPlans/ChargingPlan.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ export default defineComponent({
effectiveLimitSoc: Number,
effectivePlanSoc: Number,
effectivePlanTime: String,
effectivePlanPrecondition: Number,
effectivePlanContinuous: Boolean,
effectivePlanStrategy: Object as PropType<PlanStrategy>,
id: [String, Number],
limitEnergy: Number,
mode: String,
Expand Down
17 changes: 8 additions & 9 deletions assets/js/components/ChargingPlans/PlansSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ export default defineComponent({
effectiveLimitSoc: Number,
effectivePlanTime: String,
effectivePlanSoc: Number,
effectivePlanPrecondition: Number,
effectivePlanContinuous: Boolean,
effectivePlanStrategy: Object as PropType<PlanStrategy>,
planEnergy: Number,
limitEnergy: Number,
socBasedPlanning: Boolean,
Expand Down Expand Up @@ -162,8 +161,8 @@ export default defineComponent({
chargingPlanStrategyProps(): any {
return {
id: this.id,
precondition: this.effectivePlanPrecondition,
continuous: this.effectivePlanContinuous,
precondition: this.effectivePlanStrategy?.precondition,
continuous: this.effectivePlanStrategy?.continuous,
};
},
alreadyReached(): boolean {
Expand All @@ -186,11 +185,11 @@ export default defineComponent({
this.updatePlanDebounced();
}
},
effectivePlanPrecondition() {
this.updatePlanDebounced();
},
effectivePlanContinuous() {
this.updatePlanDebounced();
effectivePlanStrategy: {
deep: true,
handler() {
this.updatePlanDebounced();
},
},
staticPlan: {
deep: true,
Expand Down
2 changes: 2 additions & 0 deletions assets/js/components/ChargingPlans/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ export type StaticPlan = StaticSocPlan | StaticEnergyPlan;
export interface StaticSocPlan {
soc: number;
time: Date;
planStrategy?: PlanStrategy;
}

export interface StaticEnergyPlan {
energy: number;
time: Date;
planStrategy?: PlanStrategy;
}

export interface PlanStrategy {
Expand Down
7 changes: 1 addition & 6 deletions assets/js/components/Loadpoints/Loadpoint.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ const baseState = {
planActive: false,
planEnergy: 0,
planOverrun: 0,
planPrecondition: 0,
planContinuous: false,
planStrategy: { continuous: false, precondition: 0 },
planProjectedEnd: undefined,
planProjectedStart: undefined,
planTime: undefined,
Expand Down Expand Up @@ -83,8 +82,6 @@ const baseState = {
capacity: 8,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
},
{
name: "vehicle_4",
Expand All @@ -93,8 +90,6 @@ const baseState = {
capacity: 80,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
},
],
smartCostType: SMART_COST_TYPE.PRICE_FORECAST,
Expand Down
4 changes: 2 additions & 2 deletions assets/js/components/Loadpoints/Loadpoint.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ import type {
Forecast,
SMART_COST_TYPE,
} from "@/types/evcc";
import type { PlanStrategy } from "@/components/ChargingPlans/types";

export default defineComponent({
name: "Loadpoint",
Expand Down Expand Up @@ -189,8 +190,7 @@ export default defineComponent({
planTime: String as PropType<string | null>,
effectivePlanTime: String as PropType<string | null>,
effectivePlanSoc: Number,
effectivePlanPrecondition: Number,
effectivePlanContinuous: Boolean,
effectivePlanStrategy: Object as PropType<PlanStrategy>,
vehicleProviderLoggedIn: Boolean,
vehicleProviderLoginPath: String,
vehicleProviderLogoutPath: String,
Expand Down
6 changes: 0 additions & 6 deletions assets/js/components/Loadpoints/Loadpoints.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ const baseArgs = {
capacity: 8,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
},
{
name: "vehicle_4",
Expand All @@ -58,8 +56,6 @@ const baseArgs = {
capacity: 80,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
},
{
name: "vehicle_5",
Expand All @@ -68,8 +64,6 @@ const baseArgs = {
capacity: 0.46,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
},
],
smartCostType: SMART_COST_TYPE.PRICE_FORECAST,
Expand Down
2 changes: 0 additions & 2 deletions assets/js/components/Vehicles/Vehicle.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ const baseState = {
features: [],
name: "",
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
},
enabled: false,
connected: true,
Expand Down
4 changes: 2 additions & 2 deletions assets/js/components/Vehicles/Vehicle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import LimitEnergySelect from "./LimitEnergySelect.vue";
import { distanceUnit, distanceValue } from "@/units.ts";
import { defineComponent, type PropType } from "vue";
import { CHARGE_MODE, type Forecast, type Vehicle } from "@/types/evcc";
import type { PlanStrategy } from "@/components/ChargingPlans/types";

export default defineComponent({
name: "Vehicle",
Expand All @@ -103,8 +104,7 @@ export default defineComponent({
effectiveLimitSoc: Number,
effectivePlanSoc: Number,
effectivePlanTime: String,
effectivePlanPrecondition: Number,
effectivePlanContinuous: Boolean,
effectivePlanStrategy: Object as PropType<PlanStrategy>,
batteryBoostActive: Boolean,
enabled: Boolean,
heating: Boolean,
Expand Down
12 changes: 4 additions & 8 deletions assets/js/types/evcc.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { StaticPlan, RepeatingPlan } from "../components/ChargingPlans/types";
import type { StaticPlan, RepeatingPlan, PlanStrategy } from "../components/ChargingPlans/types";
import type { ForecastSlot, SolarDetails } from "../components/Forecast/types";

// react-native-webview
Expand Down Expand Up @@ -191,7 +191,7 @@ export interface ConfigLoadpoint {
smartCostLimit: number | null;
planEnergy?: number;
planTime?: string;
planPrecondition?: number;
planStrategy?: PlanStrategy;
limitEnergy?: number;
limitSoc?: number;
circuit?: string;
Expand Down Expand Up @@ -246,8 +246,7 @@ export interface Loadpoint {
effectivePlanId: number;
effectivePlanSoc: number;
effectivePlanTime: string | null;
effectivePlanPrecondition: number;
effectivePlanContinuous: boolean;
effectivePlanStrategy: PlanStrategy;
effectivePriority: number;
enableDelay: number;
enableThreshold: number;
Expand All @@ -265,8 +264,7 @@ export interface Loadpoint {
planActive: boolean;
planEnergy: number;
planOverrun: number;
planPrecondition: number;
planContinuous: boolean;
planStrategy: PlanStrategy;
planProjectedEnd: string | null;
planProjectedStart: string | null;
planTime: string | null;
Expand Down Expand Up @@ -481,8 +479,6 @@ export interface Vehicle {
limitSoc?: number;
plan?: StaticPlan;
repeatingPlans: RepeatingPlan[] | null;
planPrecondition: number;
planContinuous: boolean;
title: string;
features?: string[];
capacity?: number;
Expand Down
8 changes: 2 additions & 6 deletions core/keys/loadpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ const (
EffectiveMinCurrent = "effectiveMinCurrent" // effective min current
EffectiveMaxCurrent = "effectiveMaxCurrent" // effective max current

EffectiveLimitSoc = "effectiveLimitSoc" // effective limit soc
EffectivePlanStrategy = "effectivePlanStrategy" // effective plan strategy (deprecated, use individual fields)
EffectivePlanPrecondition = "effectivePlanPrecondition" // effective plan precondition duration
EffectivePlanContinuous = "effectivePlanContinuous" // effective plan continuous planning
EffectiveLimitSoc = "effectiveLimitSoc" // effective limit soc
EffectivePlanStrategy = "effectivePlanStrategy" // effective plan strategy

// measurements
ChargePower = "chargePower" // charge power
Expand All @@ -86,8 +84,6 @@ const (
PlanProjectedEnd = "planProjectedEnd" // charge plan ends (end of last slot)
PlanOverrun = "planOverrun" // charge plan goal not reachable in time
PlanStrategy = "planStrategy" // charge plan strategy (precondition, continuous)
PlanPrecondition = "planPrecondition" // charge plan precondition duration
PlanContinuous = "planContinuous" // charge plan continuous planning

// repeating plans
RepeatingPlans = "repeatingPlans" // key to access all repeating plans in db
Expand Down
3 changes: 1 addition & 2 deletions core/loadpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,7 @@ func (lp *Loadpoint) Prepare(site site.API, uiChan chan<- util.Param, pushChan c
// restored settings
lp.publish(keys.PlanTime, lp.planTime)
lp.publish(keys.PlanEnergy, lp.planEnergy)
lp.publish(keys.PlanPrecondition, int64(lp.planStrategy.Precondition.Seconds()))
lp.publish(keys.PlanContinuous, lp.planStrategy.Continuous)
lp.publish(keys.PlanStrategy, lp.planStrategy)
lp.publish(keys.LimitSoc, lp.limitSoc)
lp.publish(keys.LimitEnergy, lp.limitEnergy)

Expand Down
3 changes: 1 addition & 2 deletions core/loadpoint_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ func (lp *Loadpoint) setPlanStrategy(strategy api.PlanStrategy) error {
}

lp.planStrategy = strategy
lp.publish(keys.PlanPrecondition, int64(strategy.Precondition.Seconds()))
lp.publish(keys.PlanContinuous, strategy.Continuous)
lp.publish(keys.PlanStrategy, strategy)

lp.requestUpdate()

Expand Down
4 changes: 1 addition & 3 deletions core/loadpoint_effective.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ import (

// PublishEffectiveValues publishes all effective values
func (lp *Loadpoint) PublishEffectiveValues() {
strategy := lp.EffectivePlanStrategy()
lp.publish(keys.EffectivePriority, lp.EffectivePriority())
lp.publish(keys.EffectivePlanId, lp.EffectivePlanId())
lp.publish(keys.EffectivePlanTime, lp.EffectivePlanTime())
lp.publish(keys.EffectivePlanSoc, lp.EffectivePlanSoc())
lp.publish(keys.EffectivePlanStrategy, lp.EffectivePlanStrategy())
lp.publish(keys.EffectiveMinCurrent, lp.effectiveMinCurrent())
lp.publish(keys.EffectiveMaxCurrent, lp.effectiveMaxCurrent())
lp.publish(keys.EffectiveLimitSoc, lp.EffectiveLimitSoc())
lp.publish(keys.EffectivePlanPrecondition, int64(strategy.Precondition.Seconds()))
lp.publish(keys.EffectivePlanContinuous, strategy.Continuous)
}

// EffectivePriority returns the effective priority
Expand Down
66 changes: 32 additions & 34 deletions core/site_vehicles.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,24 @@ import (
)

type planStruct struct {
Soc int `json:"soc"`
Continuous bool `json:"continuous"`
Precondition int64 `json:"precondition"`
Time time.Time `json:"time"`
Soc int `json:"soc"`
Time time.Time `json:"time"`
PlanStrategy api.PlanStrategy `json:"planStrategy"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PlanStrategy has effect for the static Plan and for RepeatingPlans. Therefore I wouldn't nest into the static plan and keep it directly in vehicleStruct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andig this was your refactoring, wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andig friendly ping ;-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like this as part of the plan- a strategy always relates to a (repeating) plan. But looking at https://github.com/evcc-io/evcc/pull/26540/changes#diff-65aed087489435cf1207d29104c2436829844af8ada75323d641e2b4bdc17058R19, we also need to do this for the repeating plan.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand what's expected here, sorry.

}

type vehicleStruct struct {
Title string `json:"title"`
Icon string `json:"icon,omitempty"`
Capacity float64 `json:"capacity,omitempty"`
Phases int `json:"phases,omitempty"`
MinSoc int `json:"minSoc,omitempty"`
LimitSoc int `json:"limitSoc,omitempty"`
MinCurrent float64 `json:"minCurrent,omitempty"`
MaxCurrent float64 `json:"maxCurrent,omitempty"`
Priority int `json:"priority,omitempty"`
Features []string `json:"features,omitempty"`
Plan *planStruct `json:"plan,omitempty"`
RepeatingPlans []api.RepeatingPlan `json:"repeatingPlans"`
PlanPrecondition int64 `json:"planPrecondition"`
PlanContinuous bool `json:"planContinuous"`
Title string `json:"title"`
Icon string `json:"icon,omitempty"`
Capacity float64 `json:"capacity,omitempty"`
Phases int `json:"phases,omitempty"`
MinSoc int `json:"minSoc,omitempty"`
LimitSoc int `json:"limitSoc,omitempty"`
MinCurrent float64 `json:"minCurrent,omitempty"`
MaxCurrent float64 `json:"maxCurrent,omitempty"`
Priority int `json:"priority,omitempty"`
Features []string `json:"features,omitempty"`
Plan *planStruct `json:"plan,omitempty"`
RepeatingPlans []api.RepeatingPlan `json:"repeatingPlans"`
}

// publishVehicles returns a list of vehicle titles
Expand All @@ -48,28 +45,29 @@ func (site *Site) publishVehicles() {
}

ac := instance.OnIdentified()
strategy := v.GetPlanStrategy()

var plan *planStruct
if time, soc := v.GetPlanSoc(); !time.IsZero() {
plan = &planStruct{Soc: soc, Precondition: int64(strategy.Precondition.Seconds()), Time: time}
plan = &planStruct{
Soc: soc,
Time: time,
PlanStrategy: v.GetPlanStrategy(),
}
}

res[v.Name()] = vehicleStruct{
Title: instance.GetTitle(),
Icon: instance.Icon(),
Capacity: instance.Capacity(),
Phases: instance.Phases(),
MinSoc: v.GetMinSoc(),
LimitSoc: v.GetLimitSoc(),
MinCurrent: ac.MinCurrent,
MaxCurrent: ac.MaxCurrent,
Priority: ac.Priority,
Features: lo.Map(instance.Features(), func(f api.Feature, _ int) string { return f.String() }),
Plan: plan,
RepeatingPlans: v.GetRepeatingPlans(),
PlanPrecondition: int64(strategy.Precondition.Seconds()),
PlanContinuous: strategy.Continuous,
Title: instance.GetTitle(),
Icon: instance.Icon(),
Capacity: instance.Capacity(),
Phases: instance.Phases(),
MinSoc: v.GetMinSoc(),
LimitSoc: v.GetLimitSoc(),
MinCurrent: ac.MinCurrent,
MaxCurrent: ac.MaxCurrent,
Priority: ac.Priority,
Features: lo.Map(instance.Features(), func(f api.Feature, _ int) string { return f.String() }),
Plan: plan,
RepeatingPlans: v.GetRepeatingPlans(),
}

if lp := site.coordinator.Owner(instance); lp != nil {
Expand Down
Loading
Loading