Skip to content
Draft
Show file tree
Hide file tree
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
42 changes: 35 additions & 7 deletions api/plans.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
package api

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

type RepeatingPlan struct {
Weekdays []int `json:"weekdays"` // 0-6 (Sunday-Saturday)
Time string `json:"time"` // HH:MM
Tz string `json:"tz"` // timezone in IANA format
Soc int `json:"soc"` // target soc
Active bool `json:"active"` // active flag
Precondition int64 `json:"-" todo:"..."` // TODO deprecated
Weekdays []int `json:"weekdays"` // 0-6 (Sunday-Saturday)
Time string `json:"time"` // HH:MM
Tz string `json:"tz"` // timezone in IANA format
Soc int `json:"soc"` // target soc
Active bool `json:"active"` // active flag
}

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
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export default defineComponent({
weekdays: DEFAULT_WEEKDAYS,
time: DEFAULT_TARGET_TIME,
soc: DEFAULT_TARGET_SOC,
precondition: 0,
active: false,
tz: this.timezone(),
};
Expand Down
24 changes: 9 additions & 15 deletions assets/js/components/ChargingPlans/PlansSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
</div>
</h5>
<ChargingPlanStrategy
v-bind="chargingPlanStrategyProps"
:id="id"
:precondition="effectivePlanStrategy?.precondition"
:continuous="effectivePlanStrategy?.continuous"
:disabled="strategyDisabled"
:show="strategyOpen"
@update="updatePlanStrategy"
Expand Down Expand Up @@ -107,8 +109,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 @@ -159,13 +160,6 @@ export default defineComponent({
? { duration, plan, power, rates, targetTime, currency, smartCostType }
: null;
},
chargingPlanStrategyProps(): any {
return {
id: this.id,
precondition: this.effectivePlanPrecondition,
continuous: this.effectivePlanContinuous,
};
},
alreadyReached(): boolean {
return this.plan.duration === 0;
},
Expand All @@ -186,11 +180,11 @@ export default defineComponent({
this.updatePlanDebounced();
}
},
effectivePlanPrecondition() {
this.updatePlanDebounced();
},
effectivePlanContinuous() {
this.updatePlanDebounced();
effectivePlanStrategy: {
deep: true,
handler() {
this.updatePlanDebounced();
},
},
staticPlan: {
deep: true,
Expand Down
15 changes: 9 additions & 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,10 @@ const baseState = {
capacity: 8,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
planStrategy: {
continuous: false,
precondition: 0,
},
},
{
name: "vehicle_4",
Expand All @@ -93,8 +94,10 @@ const baseState = {
capacity: 80,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
planStrategy: {
continuous: true,
precondition: 0,
},
},
],
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
18 changes: 12 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,10 @@ const baseArgs = {
capacity: 8,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
planStrategy: {
continuous: false,
precondition: 0,
},
},
{
name: "vehicle_4",
Expand All @@ -58,8 +60,10 @@ const baseArgs = {
capacity: 80,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
planStrategy: {
continuous: true,
precondition: 0,
},
},
{
name: "vehicle_5",
Expand All @@ -68,8 +72,10 @@ const baseArgs = {
capacity: 0.46,
features: ["Offline"],
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
planStrategy: {
continuous: false,
precondition: 0,
},
},
],
smartCostType: SMART_COST_TYPE.PRICE_FORECAST,
Expand Down
6 changes: 4 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,10 @@ const baseState = {
features: [],
name: "",
repeatingPlans: [],
planPrecondition: 0,
planContinuous: false,
planStrategy: {
continuous: false,
precondition: 0,
},
},
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
13 changes: 5 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,7 @@ export interface Vehicle {
limitSoc?: number;
plan?: StaticPlan;
repeatingPlans: RepeatingPlan[] | null;
planPrecondition: number;
planContinuous: boolean;
planStrategy: PlanStrategy;
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 @@ -686,8 +686,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
12 changes: 9 additions & 3 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 All @@ -417,7 +416,14 @@ func (lp *Loadpoint) SetPlanStrategy(strategy api.PlanStrategy) error {

lp.log.DEBUG.Printf("set plan strategy: continuous=%v, precondition=%v", strategy.Continuous, strategy.Precondition)

return lp.setPlanStrategy(strategy)
if err := lp.setPlanStrategy(strategy); err != nil {
return err
}

// publish effective plan strategy immediately (we're already holding Lock)
lp.publish(keys.EffectivePlanStrategy, lp.getEffectivePlanStrategy())

return nil
}

// getPlanStrategy returns the plan strategy (no mutex)
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
Loading
Loading