Grünstromindex: fall back to co2_g_oekostrom when co2_g_standard is null (#33164)

This commit is contained in:
andig 2026-08-25 13:22:49 +02:00 • committed by GitHub
parent a66fa2fa04
commit 2b87fe2b1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 11 deletions

View file

@ -18,8 +18,8 @@ type Forecast struct {
Gsi float64 `json:"gsi"`
TimeStamp int64 `json:"timeStamp"`
Energyprice string `json:"energyprice"`
Co2GStandard int `json:"co2_g_standard"`
Co2GOekostrom int `json:"co2_g_oekostrom"`
Co2GStandard *int `json:"co2_g_standard"`
Co2GOekostrom *int `json:"co2_g_oekostrom"`
Timeframe struct {
Start int64 `json:"start"`
End int64 `json:"end"`

View file

@ -74,6 +74,13 @@ func (t *GrünStromIndex) run(done chan error) {
}
}
var data api.Rates
if err == nil {
if data = gsiRates(res); len(data) == 0 {
err = api.ErrNotAvailable
}
}
if err != nil {
if reportError(&once, done, err) {
return
@ -83,20 +90,33 @@ func (t *GrünStromIndex) run(done chan error) {
continue
}
data := make(api.Rates, 0, len(res.Forecast))
for _, r := range res.Forecast {
data = append(data, api.Rate{
Start: time.UnixMilli(r.Timeframe.Start).Local(),
End: time.UnixMilli(r.Timeframe.End).Local(),
Value: float64(r.Co2GStandard),
})
}
mergeRates(t.data, data)
once.Do(func() { close(done) })
}
}
// gsiRates maps the forecast to rates. co2_g_standard is null since mid-2026,
// fall back to co2_g_oekostrom and skip slots without either value.
func gsiRates(res corrently.Forecast) api.Rates {
data := make(api.Rates, 0, len(res.Forecast))
for _, r := range res.Forecast {
co2 := r.Co2GStandard
if co2 == nil {
co2 = r.Co2GOekostrom
}
if co2 == nil {
continue
}
data = append(data, api.Rate{
Start: time.UnixMilli(r.Timeframe.Start).Local(),
End: time.UnixMilli(r.Timeframe.End).Local(),
Value: float64(*co2),
})
}
return data
}
// Rates implements the api.Tariff interface
func (t *GrünStromIndex) Rates() (api.Rates, error) {
var res api.Rates

View file

@ -0,0 +1,25 @@
package tariff
import (
"encoding/json"
"testing"
"github.com/evcc-io/evcc/tariff/corrently"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGsiRates(t *testing.T) {
// co2_g_standard is null since mid-2026, co2_g_oekostrom is the fallback
var res corrently.Forecast
require.NoError(t, json.Unmarshal([]byte(`{"forecast":[
{"co2_g_standard":348,"co2_g_oekostrom":23,"timeframe":{"start":1787652000000,"end":1787655600000}},
{"co2_g_standard":null,"co2_g_oekostrom":25,"timeframe":{"start":1787655600000,"end":1787659200000}},
{"co2_g_standard":null,"co2_g_oekostrom":null,"timeframe":{"start":1787659200000,"end":1787662800000}}
]}`), &res))
rates := gsiRates(res)
require.Len(t, rates, 2)
assert.Equal(t, 348.0, rates[0].Value)
assert.Equal(t, 25.0, rates[1].Value)
}