diff --git a/api/plans.go b/api/plans.go index 33ae03b252..deb2ecf42a 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,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 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(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 +} diff --git a/core/keys/loadpoint.go b/core/keys/loadpoint.go index 7b6598515a..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 @@ -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 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() diff --git a/core/loadpoint_effective.go b/core/loadpoint_effective.go index 358f1d038f..58d9cea32d 100644 --- a/core/loadpoint_effective.go +++ b/core/loadpoint_effective.go @@ -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 diff --git a/core/site_vehicles.go b/core/site_vehicles.go index f4fc55215f..37294e0b7b 100644 --- a/core/site_vehicles.go +++ b/core/site_vehicles.go @@ -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"` } 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 @@ -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 { 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 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 }