Tariffs: add units (#5718)

This commit is contained in:
andig 2023-01-08 15:10:33 +01:00
parent 355fcea14f
commit b4f2da5ef5
9 changed files with 96 additions and 24 deletions

View file

@ -199,6 +199,7 @@ type Rates []Rate
// Tariff is a tariff capable of retrieving tariff rates
type Tariff interface {
Unit() string
Rates() (Rates, error)
}

View file

@ -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
}

View file

@ -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 {

View file

@ -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))
}

View file

@ -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()

View file

@ -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()

View file

@ -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

View file

@ -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()

View file

@ -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()