diff --git a/api/globalconfig/types.go b/api/globalconfig/types.go index 631b4e4e2..eace135f8 100644 --- a/api/globalconfig/types.go +++ b/api/globalconfig/types.go @@ -79,7 +79,7 @@ type Go struct { type ModbusProxy struct { Port int `json:"port"` ReadOnly string `yaml:",omitempty" json:"readonly,omitempty"` - modbus.Settings `mapstructure:",squash" yaml:",inline,omitempty" json:"settings,omitempty"` + modbus.Settings `mapstructure:",squash" yaml:",inline,omitempty" json:"settings"` } var _ api.Redactor = (*Hems)(nil) diff --git a/core/prioritizer/prioritizer.go b/core/prioritizer/prioritizer.go index 6cdb88866..4111fb20b 100644 --- a/core/prioritizer/prioritizer.go +++ b/core/prioritizer/prioritizer.go @@ -2,6 +2,7 @@ package prioritizer import ( "fmt" + "strings" "sync" "github.com/evcc-io/evcc/api" @@ -35,18 +36,18 @@ func (p *Prioritizer) GetChargePowerFlexibility(lp loadpoint.API) float64 { var ( reduceBy float64 - msg string + msg strings.Builder ) for lp, power := range p.demand { if lp.EffectivePriority() < prio && power > 0 { reduceBy += power - msg += fmt.Sprintf("%.0fW from %s at prio %d, ", power, lp.GetTitle(), lp.EffectivePriority()) + msg.WriteString(fmt.Sprintf("%.0fW from %s at prio %d, ", power, lp.GetTitle(), lp.EffectivePriority())) } } if p.log != nil && reduceBy > 0 { - p.log.DEBUG.Printf("lp %s at prio %d gets additional %stotal %.0fW\n", lp.GetTitle(), lp.EffectivePriority(), msg, reduceBy) + p.log.DEBUG.Printf("lp %s at prio %d gets additional %stotal %.0fW\n", lp.GetTitle(), lp.EffectivePriority(), msg.String(), reduceBy) } return reduceBy diff --git a/core/site_tariffs.go b/core/site_tariffs.go index f26a7ffd5..e39424827 100644 --- a/core/site_tariffs.go +++ b/core/site_tariffs.go @@ -26,11 +26,11 @@ func (s forecastSeries) MarshalBytes() ([]byte, error) { } type solarDetails struct { - Scale float64 `json:"scale"` // scale factor yield/forecasted today, 1 if unscaled - Today dailyDetails `json:"today,omitempty"` // tomorrow - Tomorrow dailyDetails `json:"tomorrow,omitempty"` // tomorrow - DayAfterTomorrow dailyDetails `json:"dayAfterTomorrow,omitempty"` // day after tomorrow - Timeseries timeseries `json:"timeseries,omitempty"` // timeseries of forecasted energy + Scale float64 `json:"scale"` // scale factor yield/forecasted today, 1 if unscaled + Today dailyDetails `json:"today"` // tomorrow + Tomorrow dailyDetails `json:"tomorrow"` // tomorrow + DayAfterTomorrow dailyDetails `json:"dayAfterTomorrow"` // day after tomorrow + Timeseries timeseries `json:"timeseries,omitempty"` // timeseries of forecasted energy } var _ api.BytesMarshaler = (*solarDetails)(nil) diff --git a/messenger/hub.go b/messenger/hub.go index 22bf694e2..c8c78b368 100644 --- a/messenger/hub.go +++ b/messenger/hub.go @@ -2,6 +2,7 @@ package messenger import ( "fmt" + "maps" "reflect" "strings" "text/template" @@ -105,9 +106,7 @@ func (h *Hub) apply(ev Event, tmpl string) (string, error) { } // event-specific attributes override cache values - for k, v := range ev.Attributes { - attr[k] = v - } + maps.Copy(attr, ev.Attributes) return util.ReplaceFormatted(tmpl, attr) } diff --git a/meter/dsmr_test.go b/meter/dsmr_test.go index 5ef977f95..e856b4c49 100644 --- a/meter/dsmr_test.go +++ b/meter/dsmr_test.go @@ -247,8 +247,7 @@ func assertReadings(t *testing.T, m api.Meter) { func TestDsmrTCP(t *testing.T) { addr := serveTCP(t, dsmrFrame(dsmrTelegram50)) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() m, err := NewDsmr(ctx, addr, time.Second) require.NoError(t, err) @@ -285,8 +284,7 @@ func TestDsmrWebSocket(t *testing.T) { uri := "ws" + strings.TrimPrefix(srv.URL, "http") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() m, err := NewDsmr(ctx, uri, time.Second) require.NoError(t, err) @@ -307,8 +305,7 @@ func TestDsmrIgnoresGarbage(t *testing.T) { addr := serveTCP(t, payload) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() m, err := NewDsmr(ctx, addr, time.Second) require.NoError(t, err) @@ -398,8 +395,7 @@ func newTestDsmr(frame map[string]string) *Dsmr { func TestDsmrADN(t *testing.T) { addr := serveTCP(t, dsmrFrame(dsmrTelegramADN)) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() m, err := NewDsmr(ctx, addr, time.Second) require.NoError(t, err) @@ -445,8 +441,7 @@ func TestDsmrADN(t *testing.T) { func TestDsmrExport(t *testing.T) { addr := serveTCP(t, dsmrFrame(dsmrTelegramExport)) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() m, err := NewDsmr(ctx, addr, time.Second) require.NoError(t, err) diff --git a/util/homeassistant/connection.go b/util/homeassistant/connection.go index e35ee29b6..f94e5a715 100644 --- a/util/homeassistant/connection.go +++ b/util/homeassistant/connection.go @@ -202,7 +202,7 @@ func NewStatusMap(a, b, c string) (StatusMap, error) { {api.StatusB, b}, {api.StatusC, c}, } { - for _, s := range strings.Split(e.states, ",") { + for s := range strings.SplitSeq(e.states, ",") { if s = strings.ToLower(strings.TrimSpace(s)); s != "" { if status, ok := res[s]; ok { return nil, fmt.Errorf("status %s: duplicate state '%s', already mapped to %s", e.status, s, status) diff --git a/util/logstash/log_test.go b/util/logstash/log_test.go index af0c7a144..aa2614827 100644 --- a/util/logstash/log_test.go +++ b/util/logstash/log_test.go @@ -45,7 +45,7 @@ func TestTraceBudget(t *testing.T) { log.Write([]byte(s2)) for i := range 100 { - log.Write([]byte(fmt.Sprintf("[mqtt ] TRACE send %d", i))) + log.Write(fmt.Appendf(nil, "[mqtt ] TRACE send %d", i)) } assert.Equal(t, []string{s2}, log.All(nil, jww.LevelDebug, 0)) diff --git a/util/sponsor/auth.go b/util/sponsor/auth.go index 63107af3e..ed225fccf 100644 --- a/util/sponsor/auth.go +++ b/util/sponsor/auth.go @@ -137,7 +137,7 @@ func redactToken(token string) string { type Status struct { Name string `json:"name"` - ExpiresAt time.Time `json:"expiresAt,omitempty"` + ExpiresAt time.Time `json:"expiresAt"` ExpiresSoon bool `json:"expiresSoon,omitempty"` Token string `json:"token,omitempty"` } diff --git a/util/sponsor/pulsares.go b/util/sponsor/pulsares.go index 66bf88458..f898a37ad 100644 --- a/util/sponsor/pulsares.go +++ b/util/sponsor/pulsares.go @@ -38,7 +38,7 @@ func checkPulsares() (string, error) { _ = f.Close() }) - var token string + var token strings.Builder b := make([]byte, 512) for { @@ -47,9 +47,9 @@ func checkPulsares() (string, error) { return "", nil } - token += string(b[:n]) + token.WriteString(string(b[:n])) - if token, ok := strings.CutSuffix(token, "\x04"); ok { + if token, ok := strings.CutSuffix(token.String(), "\x04"); ok { return token, nil } } diff --git a/util/templates/types.go b/util/templates/types.go index 55dbe208c..b106afd1b 100644 --- a/util/templates/types.go +++ b/util/templates/types.go @@ -327,7 +327,7 @@ func (p Param) MarshalJSON() ([]byte, error) { // Product contains naming information about a product a template supports type Product struct { Brand string // product brand - Description TextLanguage `json:",omitempty"` // product name + Description TextLanguage // product name Capabilities []Capability `json:",omitempty"` // appended to template-level capabilities }