From b809f581ba3af7d9f4f63d6abd1bbb85fdd70bf8 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 13:56:52 +0100 Subject: [PATCH 1/9] Planner: drop deprecated publishing keys (BC) --- api/plans.go | 29 ++++++++++++++++++++++++++++- core/keys/loadpoint.go | 2 -- core/loadpoint.go | 3 +-- core/loadpoint_api.go | 3 +-- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/api/plans.go b/api/plans.go index 33ae03b252..57f17e730b 100644 --- a/api/plans.go +++ b/api/plans.go @@ -1,6 +1,9 @@ package api -import "time" +import ( + "encoding/json" + "time" +) type RepeatingPlan struct { Weekdays []int `json:"weekdays"` // 0-6 (Sunday-Saturday) @@ -15,3 +18,27 @@ 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 int `json:"precondition"` // precondition duration in seconds +} + +func (ps *PlanStrategy) MarshalJSON() ([]byte, error) { + return json.Marshal(planStrategy{ + Continuous: ps.Continuous, + Precondition: int(ps.Precondition.Seconds()), + }) +} + +func (ps *PlanStrategy) UnmarshalJSON(bytes []byte) error { + var res planStrategy + if err := json.Unmarshal(bytes, &res); err != nil { + return err + } + + ps.Continuous = res.Continuous + ps.Precondition = ps.Precondition * time.Second + + return nil +} diff --git a/core/keys/loadpoint.go b/core/keys/loadpoint.go index 7b6598515a..10f1cc55d8 100644 --- a/core/keys/loadpoint.go +++ b/core/keys/loadpoint.go @@ -86,8 +86,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 diff --git a/core/loadpoint.go b/core/loadpoint.go index 201205938a..13169475b2 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -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) diff --git a/core/loadpoint_api.go b/core/loadpoint_api.go index 4eb9e8eac5..dabdfd3644 100644 --- a/core/loadpoint_api.go +++ b/core/loadpoint_api.go @@ -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() From 16b0a9a0737a7927c78e5f497757325b6dde5162 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:06:18 +0100 Subject: [PATCH 2/9] wip --- api/plans.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/plans.go b/api/plans.go index 57f17e730b..625ad8e05c 100644 --- a/api/plans.go +++ b/api/plans.go @@ -38,7 +38,7 @@ func (ps *PlanStrategy) UnmarshalJSON(bytes []byte) error { } ps.Continuous = res.Continuous - ps.Precondition = ps.Precondition * time.Second + ps.Precondition = time.Duration(res.Precondition) * time.Second return nil } From dc5c248cbb8e9efed1cccc03a326e681bb66ab7d Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:27:10 +0100 Subject: [PATCH 3/9] wip --- api/plans.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/plans.go b/api/plans.go index 625ad8e05c..d38c9b283f 100644 --- a/api/plans.go +++ b/api/plans.go @@ -31,9 +31,9 @@ func (ps *PlanStrategy) MarshalJSON() ([]byte, error) { }) } -func (ps *PlanStrategy) UnmarshalJSON(bytes []byte) error { +func (ps *PlanStrategy) UnmarshalJSON(b []byte) error { var res planStrategy - if err := json.Unmarshal(bytes, &res); err != nil { + if err := json.Unmarshal(b, &res); err != nil { return err } From a83201ae3ab33debe9f2eee2762782b8a299edb2 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:27:53 +0100 Subject: [PATCH 4/9] wip --- api/plans.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/plans.go b/api/plans.go index d38c9b283f..21bd73e1b6 100644 --- a/api/plans.go +++ b/api/plans.go @@ -37,8 +37,10 @@ func (ps *PlanStrategy) UnmarshalJSON(b []byte) error { return err } - ps.Continuous = res.Continuous - ps.Precondition = time.Duration(res.Precondition) * time.Second + *ps = PlanStrategy{ + Continuous: res.Continuous, + Precondition: time.Duration(res.Precondition) * time.Second, + } return nil } From d0a709637d1cdaebefc433ec09dc3a862e35169a Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:29:55 +0100 Subject: [PATCH 5/9] wip --- api/plans.go | 4 ++-- tariff/solcast/types.go | 4 ++-- util/shortrfc3339/shortrfc3339.go | 4 ++-- vehicle/psa/duration.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/plans.go b/api/plans.go index 21bd73e1b6..deb2ecf42a 100644 --- a/api/plans.go +++ b/api/plans.go @@ -31,9 +31,9 @@ func (ps *PlanStrategy) MarshalJSON() ([]byte, error) { }) } -func (ps *PlanStrategy) UnmarshalJSON(b []byte) error { +func (ps *PlanStrategy) UnmarshalJSON(data []byte) error { var res planStrategy - if err := json.Unmarshal(b, &res); err != nil { + if err := json.Unmarshal(data, &res); err != nil { return err } diff --git a/tariff/solcast/types.go b/tariff/solcast/types.go index a37af2efb9..c878f081c4 100644 --- a/tariff/solcast/types.go +++ b/tariff/solcast/types.go @@ -24,8 +24,8 @@ func (d *Duration) Duration() time.Duration { return time.Duration(*d) } -func (d *Duration) UnmarshalJSON(b []byte) error { - val, err := iso8601.ParseDuration(string(b)) +func (d *Duration) UnmarshalJSON(data []byte) error { + val, err := iso8601.ParseDuration(string(data)) if err != nil { return err } diff --git a/util/shortrfc3339/shortrfc3339.go b/util/shortrfc3339/shortrfc3339.go index 7de6935635..b1912dc7fa 100644 --- a/util/shortrfc3339/shortrfc3339.go +++ b/util/shortrfc3339/shortrfc3339.go @@ -15,8 +15,8 @@ type Timestamp struct { // Layout is the time.Parse compliant parsing string for use when parsing Shortened RFC-3339 compliant timestamps. const Layout = "2006-01-02T15:04Z" -func (ct *Timestamp) UnmarshalJSON(b []byte) (err error) { - s := strings.Trim(string(b), "\"") +func (ct *Timestamp) UnmarshalJSON(data []byte) (err error) { + s := strings.Trim(string(data), "\"") if s == "null" { ct.Time = time.Time{} return diff --git a/vehicle/psa/duration.go b/vehicle/psa/duration.go index 570a1885cb..334c1374b2 100644 --- a/vehicle/psa/duration.go +++ b/vehicle/psa/duration.go @@ -14,9 +14,9 @@ type Duration struct { } // UnmarshalJSON implements json.Unmarshaler -func (d *Duration) UnmarshalJSON(b []byte) error { +func (d *Duration) UnmarshalJSON(data []byte) error { var v any - if err := json.Unmarshal(b, &v); err != nil { + if err := json.Unmarshal(data, &v); err != nil { return err } From c49fa5928215ac5283712e8d7ae03747e4dd79f0 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:42:52 +0100 Subject: [PATCH 6/9] wip --- core/keys/loadpoint.go | 6 ++-- core/loadpoint_effective.go | 4 +-- core/site_vehicles.go | 55 ++++++++++++++++++------------------- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/core/keys/loadpoint.go b/core/keys/loadpoint.go index 10f1cc55d8..f751470d5f 100644 --- a/core/keys/loadpoint.go +++ b/core/keys/loadpoint.go @@ -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 (deprecated, use individual fields) // measurements ChargePower = "chargePower" // charge power diff --git a/core/loadpoint_effective.go b/core/loadpoint_effective.go index 358f1d038f..8d9d0d245b 100644 --- a/core/loadpoint_effective.go +++ b/core/loadpoint_effective.go @@ -12,7 +12,6 @@ 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()) @@ -20,8 +19,7 @@ func (lp *Loadpoint) PublishEffectiveValues() { 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) + lp.publish(keys.EffectivePlanStrategy, lp.EffectivePlanStrategy()) } // EffectivePriority returns the effective priority diff --git a/core/site_vehicles.go b/core/site_vehicles.go index f4fc55215f..29913db8c7 100644 --- a/core/site_vehicles.go +++ b/core/site_vehicles.go @@ -20,20 +20,19 @@ type planStruct struct { } 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"` + PlanStrategy api.PlanStrategy `json:"planStrategy"` } // publishVehicles returns a list of vehicle titles @@ -48,7 +47,6 @@ func (site *Site) publishVehicles() { } ac := instance.OnIdentified() - strategy := v.GetPlanStrategy() var plan *planStruct if time, soc := v.GetPlanSoc(); !time.IsZero() { @@ -56,20 +54,19 @@ func (site *Site) publishVehicles() { } 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(), + PlanStrategy: v.GetPlanStrategy(), } if lp := site.coordinator.Owner(instance); lp != nil { From bb68c10ce3b9f404bc20d366beb2766f1dc57b9e Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:49:12 +0100 Subject: [PATCH 7/9] wip --- core/site_vehicles.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/site_vehicles.go b/core/site_vehicles.go index 29913db8c7..37294e0b7b 100644 --- a/core/site_vehicles.go +++ b/core/site_vehicles.go @@ -13,10 +13,9 @@ 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"` } type vehicleStruct struct { @@ -32,7 +31,6 @@ type vehicleStruct struct { Features []string `json:"features,omitempty"` Plan *planStruct `json:"plan,omitempty"` RepeatingPlans []api.RepeatingPlan `json:"repeatingPlans"` - PlanStrategy api.PlanStrategy `json:"planStrategy"` } // publishVehicles returns a list of vehicle titles @@ -50,7 +48,11 @@ func (site *Site) publishVehicles() { 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{ @@ -66,7 +68,6 @@ func (site *Site) publishVehicles() { Features: lo.Map(instance.Features(), func(f api.Feature, _ int) string { return f.String() }), Plan: plan, RepeatingPlans: v.GetRepeatingPlans(), - PlanStrategy: v.GetPlanStrategy(), } if lp := site.coordinator.Owner(instance); lp != nil { From 608c7bb0fa4b24ff12546f9224dcc1a21584ec23 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:53:45 +0100 Subject: [PATCH 8/9] wip --- core/loadpoint_effective.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/loadpoint_effective.go b/core/loadpoint_effective.go index 8d9d0d245b..58d9cea32d 100644 --- a/core/loadpoint_effective.go +++ b/core/loadpoint_effective.go @@ -16,10 +16,10 @@ func (lp *Loadpoint) PublishEffectiveValues() { 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.EffectivePlanStrategy, lp.EffectivePlanStrategy()) } // EffectivePriority returns the effective priority From e2859576250d0f0ecd6632b46f4cdf516ea2c74d Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 31 Dec 2025 14:55:28 +0100 Subject: [PATCH 9/9] wip --- core/vehicle/adapter.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/vehicle/adapter.go b/core/vehicle/adapter.go index 40fbaf5eb8..f7a1bf6b9c 100644 --- a/core/vehicle/adapter.go +++ b/core/vehicle/adapter.go @@ -153,7 +153,6 @@ func (v *adapter) SetPlanStrategy(planStrategy api.PlanStrategy) error { return err } - v.log.DEBUG.Printf("update plan strategy for vehicle %s (precondition: %vs, continuous: %v)", v.name, planStrategy.Continuous, planStrategy.Precondition) v.publish() return nil