diff --git a/api/api.go b/api/api.go index 79635d5eb..7047b92fc 100644 --- a/api/api.go +++ b/api/api.go @@ -199,6 +199,7 @@ type Rates []Rate // Tariff is a tariff capable of retrieving tariff rates type Tariff interface { + Unit() string Rates() (Rates, error) } diff --git a/meter/tibber/client.go b/meter/tibber/client.go index 05d875699..ee32bbc3d 100644 --- a/meter/tibber/client.go +++ b/meter/tibber/client.go @@ -30,7 +30,7 @@ func NewClient(log *util.Logger, token string) *Client { } } -func (c *Client) DefaultHomeID() (string, error) { +func (c *Client) Home() (Home, error) { var res struct { Viewer struct { Homes []Home @@ -41,12 +41,17 @@ func (c *Client) DefaultHomeID() (string, error) { defer cancel() if err := c.Query(ctx, &res, nil); err != nil { - return "", err + return Home{}, err } if len(res.Viewer.Homes) != 1 { - return "", fmt.Errorf("could not determine home id: %v", res.Viewer.Homes) + return Home{}, fmt.Errorf("could not determine home id: %v", res.Viewer.Homes) } - return res.Viewer.Homes[0].ID, nil + return res.Viewer.Homes[0], nil +} + +func (c *Client) DefaultHomeID() (string, error) { + home, err := c.Home() + return home.ID, err } diff --git a/meter/tibber/types.go b/meter/tibber/types.go index 8c669d488..00fe38e92 100644 --- a/meter/tibber/types.go +++ b/meter/tibber/types.go @@ -14,6 +14,7 @@ type Home struct { MeteringPointData struct { GridCompany string } + CurrentSubscription Subscription } type Address struct { @@ -23,18 +24,20 @@ type Address struct { type Subscription struct { ID string Status string - PriceInfo struct { - Current PriceInfo - Today []PriceInfo - Tomorrow []PriceInfo - } + PriceInfo PriceInfo } type PriceInfo struct { - Level string - StartsAt time.Time - Total float64 - // Energy, Tax float64 + Current Price + Today, Tomorrow []Price +} + +type Price struct { + Currency string + StartsAt time.Time + Total float64 + Energy, Tax float64 + // Level string } type LiveMeasurement struct { diff --git a/mock/mock_api.go b/mock/mock_api.go index 161d0d58a..e58166cd6 100644 --- a/mock/mock_api.go +++ b/mock/mock_api.go @@ -528,3 +528,17 @@ func (mr *MockTariffMockRecorder) Rates() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rates", reflect.TypeOf((*MockTariff)(nil).Rates)) } + +// Unit mocks base method. +func (m *MockTariff) Unit() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Unit") + ret0, _ := ret[0].(string) + return ret0 +} + +// Unit indicates an expected call of Unit. +func (mr *MockTariffMockRecorder) Unit() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unit", reflect.TypeOf((*MockTariff)(nil).Unit)) +} diff --git a/tariff/awattar.go b/tariff/awattar.go index 69788ddb7..fcbccf8a8 100644 --- a/tariff/awattar.go +++ b/tariff/awattar.go @@ -16,6 +16,7 @@ type Awattar struct { mux sync.Mutex log *util.Logger uri string + unit string data api.Rates updated time.Time } @@ -28,8 +29,9 @@ func init() { func NewAwattarFromConfig(other map[string]interface{}) (api.Tariff, error) { cc := struct { - Cheap any // TODO deprecated - Region string + Cheap any // TODO deprecated + Currency string + Region string }{ Region: "DE", } @@ -38,9 +40,14 @@ func NewAwattarFromConfig(other map[string]interface{}) (api.Tariff, error) { return nil, err } + if cc.Currency == "" { + cc.Currency = "EUR" + } + t := &Awattar{ - log: util.NewLogger("awattar"), - uri: fmt.Sprintf(awattar.RegionURI, strings.ToLower(cc.Region)), + log: util.NewLogger("awattar"), + unit: cc.Currency, + uri: fmt.Sprintf(awattar.RegionURI, strings.ToLower(cc.Region)), } // TODO deprecated @@ -85,6 +92,11 @@ func (t *Awattar) run(done chan error) { } } +// Unit implements the api.Tariff interface +func (t *Awattar) Unit() string { + return t.unit +} + // Rates implements the api.Tariff interface func (t *Awattar) Rates() (api.Rates, error) { t.mux.Lock() diff --git a/tariff/electricitymaps.go b/tariff/electricitymaps.go index 2d6d2af06..c82b6cbbc 100644 --- a/tariff/electricitymaps.go +++ b/tariff/electricitymaps.go @@ -102,6 +102,11 @@ func (t *ElectricityMaps) run(done chan error) { } } +// Unit implements the api.Tariff interface +func (t *ElectricityMaps) Unit() string { + return "gCO2eq" +} + func (t *ElectricityMaps) Rates() (api.Rates, error) { t.mux.Lock() defer t.mux.Unlock() diff --git a/tariff/fixed.go b/tariff/fixed.go index d7b37abf5..2bc945f57 100644 --- a/tariff/fixed.go +++ b/tariff/fixed.go @@ -12,6 +12,7 @@ import ( ) type Fixed struct { + unit string clock clock.Clock zones fixed.Zones } @@ -24,8 +25,9 @@ func init() { func NewFixedFromConfig(other map[string]interface{}) (api.Tariff, error) { var cc struct { - Price float64 - Zones []struct { + Currency string + Price float64 + Zones []struct { Price float64 Days, Hours string } @@ -35,7 +37,12 @@ func NewFixedFromConfig(other map[string]interface{}) (api.Tariff, error) { return nil, err } + if cc.Currency == "" { + cc.Currency = "EUR" + } + t := &Fixed{ + unit: cc.Currency, clock: clock.New(), zones: []fixed.Zone{ {Price: cc.Price}, // full week is implicit @@ -75,6 +82,11 @@ func NewFixedFromConfig(other map[string]interface{}) (api.Tariff, error) { return t, nil } +// Unit implements the api.Tariff interface +func (t *Fixed) Unit() string { + return t.unit +} + // Rates implements the api.Tariff interface func (t *Fixed) Rates() (api.Rates, error) { var res api.Rates diff --git a/tariff/gsi.go b/tariff/gruenstromindex.go similarity index 95% rename from tariff/gsi.go rename to tariff/gruenstromindex.go index a64b90c10..fe12fd130 100644 --- a/tariff/gsi.go +++ b/tariff/gruenstromindex.go @@ -113,7 +113,7 @@ func (t *GrünStromIndex) run(done chan error) { t.data = make(api.Rates, 0, len(res.Forecast)) for _, r := range res.Forecast { t.data = append(t.data, api.Rate{ - Price: 100 - r.Gsi, // gsi to cost + Price: float64(r.Co2GStandard), Start: time.UnixMilli(r.Timeframe.Start), End: time.UnixMilli(r.Timeframe.End), }) @@ -123,6 +123,11 @@ func (t *GrünStromIndex) run(done chan error) { } } +// Unit implements the api.Tariff interface +func (t *GrünStromIndex) Unit() string { + return "gCO2eq" +} + // Rates implements the api.Tariff interface func (t *GrünStromIndex) Rates() (api.Rates, error) { t.mux.Lock() diff --git a/tariff/tibber.go b/tariff/tibber.go index 0fbc50f00..497b51494 100644 --- a/tariff/tibber.go +++ b/tariff/tibber.go @@ -17,6 +17,7 @@ type Tibber struct { mux sync.Mutex log *util.Logger homeID string + unit string client *tibber.Client data api.Rates updated time.Time @@ -32,6 +33,7 @@ func NewTibberFromConfig(other map[string]interface{}) (api.Tariff, error) { var cc struct { Token string HomeID string + Unit string Cheap any // TODO deprecated } @@ -48,14 +50,22 @@ func NewTibberFromConfig(other map[string]interface{}) (api.Tariff, error) { t := &Tibber{ log: log, homeID: cc.HomeID, + unit: cc.Unit, client: tibber.NewClient(log, cc.Token), } - if t.homeID == "" { - var err error - if t.homeID, err = t.client.DefaultHomeID(); err != nil { + if t.homeID == "" || t.unit == "" { + home, err := t.client.Home() + if err != nil { return nil, err } + + if t.homeID == "" { + t.homeID = home.ID + } + if t.unit == "" { + t.unit = home.CurrentSubscription.PriceInfo.Current.Currency + } } // TODO deprecated @@ -112,7 +122,7 @@ func (t *Tibber) run(done chan error) { } } -func (t *Tibber) rates(pi []tibber.PriceInfo) api.Rates { +func (t *Tibber) rates(pi []tibber.Price) api.Rates { data := make(api.Rates, 0, len(pi)) for _, r := range pi { ar := api.Rate{ @@ -125,6 +135,11 @@ func (t *Tibber) rates(pi []tibber.PriceInfo) api.Rates { return data } +// Unit implements the api.Tariff interface +func (t *Tibber) Unit() string { + return t.unit +} + // Rates implements the api.Tariff interface func (t *Tibber) Rates() (api.Rates, error) { t.mux.Lock()