Custom charger: add optional finish timer (#29600)
This commit is contained in:
parent
0178d32302
commit
975caea21c
7 changed files with 92 additions and 11 deletions
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
reg "github.com/evcc-io/evcc/util/registry"
|
||||
)
|
||||
|
|
@ -163,3 +164,24 @@ func (c *Config) BytesSetter(ctx context.Context, param string) (func([]byte) er
|
|||
|
||||
return prov.BytesSetter(param)
|
||||
}
|
||||
|
||||
// TimeGetter returns a getter that parses the plugin value as an estimated finish time.
|
||||
// The value may be an RFC3339 timestamp, a Go duration string, or a numeric number of seconds.
|
||||
func (c *Config) TimeGetter(ctx context.Context) (func() (time.Time, error), error) {
|
||||
if c == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
stringG, err := c.StringGetter(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func() (time.Time, error) {
|
||||
s, err := stringG()
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return parseRelativeTime(s)
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
|
|
@ -42,3 +43,38 @@ func parseFloat(payload string) (float64, error) {
|
|||
}
|
||||
return f, err
|
||||
}
|
||||
|
||||
// unixThreshold is the Unix timestamp for 2026-01-01 00:00:00 UTC, used to distinguish
|
||||
// Unix timestamps from duration-in-seconds when parsing numeric finish times.
|
||||
const unixThreshold = 1767225600
|
||||
|
||||
// parseRelativeTime parses a string into an absolute time.Time.
|
||||
// Supported formats:
|
||||
// - RFC3339 timestamp (e.g. "2026-05-03T14:00:00Z") → interpreted as absolute time
|
||||
// - Go duration string (e.g. "1h30m") → interpreted as remaining duration, added to time.Now()
|
||||
// - Numeric string ≥ 1767225600 (e.g. "1767225600") → interpreted as Unix timestamp (absolute time)
|
||||
// - Numeric string < 1767225600 (e.g. "5400") → interpreted as remaining seconds, added to time.Now()
|
||||
//
|
||||
// For relative formats, time.Now() is evaluated at the time of each call, providing a
|
||||
// fresh estimate. This matches the behavior of hardcoded charger/vehicle implementations.
|
||||
func parseRelativeTime(s string) (time.Time, error) {
|
||||
// Try RFC3339 timestamp first (absolute time)
|
||||
if t, err := time.Parse(time.RFC3339, s); err == nil {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// Try Go duration string (relative)
|
||||
if d, err := time.ParseDuration(s); err == nil {
|
||||
return time.Now().Add(d), nil
|
||||
}
|
||||
|
||||
// Try numeric: Unix timestamp (absolute) or duration in seconds (relative)
|
||||
if f, err := strconv.ParseFloat(s, 64); err == nil {
|
||||
if f >= unixThreshold {
|
||||
return time.Unix(int64(f), 0), nil
|
||||
}
|
||||
return time.Now().Add(time.Duration(f * float64(time.Second))), nil
|
||||
}
|
||||
|
||||
return time.Time{}, fmt.Errorf("invalid finish time: %s", s)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue