Add configurable custom tariff (#10306)

This commit is contained in:
andig 2023-10-14 16:52:17 +02:00 • committed by GitHub
parent 3b11d0e253
commit 7ad03ecc34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 104 additions and 17 deletions

View file

@ -8,5 +8,6 @@ const (
_ TariffType = iota
TariffTypePriceStatic
TariffTypePriceDynamic
TariffTypePriceForecast
TariffTypeCo2
)

View file

@ -7,11 +7,11 @@ import (
"strings"
)
const _TariffTypeName = "pricestaticpricedynamicco2"
const _TariffTypeName = "pricestaticpricedynamicpriceforecastco2"
var _TariffTypeIndex = [...]uint8{0, 11, 23, 26}
var _TariffTypeIndex = [...]uint8{0, 11, 23, 36, 39}
const _TariffTypeLowerName = "pricestaticpricedynamicco2"
const _TariffTypeLowerName = "pricestaticpricedynamicpriceforecastco2"
func (i TariffType) String() string {
i -= 1
@ -27,24 +27,28 @@ func _TariffTypeNoOp() {
var x [1]struct{}
_ = x[TariffTypePriceStatic-(1)]
_ = x[TariffTypePriceDynamic-(2)]
_ = x[TariffTypeCo2-(3)]
_ = x[TariffTypePriceForecast-(3)]
_ = x[TariffTypeCo2-(4)]
}
var _TariffTypeValues = []TariffType{TariffTypePriceStatic, TariffTypePriceDynamic, TariffTypeCo2}
var _TariffTypeValues = []TariffType{TariffTypePriceStatic, TariffTypePriceDynamic, TariffTypePriceForecast, TariffTypeCo2}
var _TariffTypeNameToValueMap = map[string]TariffType{
_TariffTypeName[0:11]: TariffTypePriceStatic,
_TariffTypeLowerName[0:11]: TariffTypePriceStatic,
_TariffTypeName[11:23]: TariffTypePriceDynamic,
_TariffTypeLowerName[11:23]: TariffTypePriceDynamic,
_TariffTypeName[23:26]: TariffTypeCo2,
_TariffTypeLowerName[23:26]: TariffTypeCo2,
_TariffTypeName[23:36]: TariffTypePriceForecast,
_TariffTypeLowerName[23:36]: TariffTypePriceForecast,
_TariffTypeName[36:39]: TariffTypeCo2,
_TariffTypeLowerName[36:39]: TariffTypeCo2,
}
var _TariffTypeNames = []string{
_TariffTypeName[0:11],
_TariffTypeName[11:23],
_TariffTypeName[23:26],
_TariffTypeName[23:36],
_TariffTypeName[36:39],
}
// TariffTypeString retrieves an enum value from the enum constants string name.

View file

@ -171,7 +171,7 @@ import GridSettingsModal from "../GridSettingsModal.vue";
import formatter from "../../mixins/formatter";
import AnimatedNumber from "../AnimatedNumber.vue";
import settings from "../../settings";
import { CO2_TYPE, PRICE_DYNAMIC_TYPE } from "../../units";
import { CO2_TYPE, PRICE_DYNAMIC_TYPE, PRICE_FORECAST_TYPE } from "../../units";
import collector from "../../mixins/collector";
import BatterySettingsModal from "../BatterySettingsModal.vue";
@ -216,7 +216,7 @@ export default {
},
computed: {
smartCostAvailable: function () {
return [CO2_TYPE, PRICE_DYNAMIC_TYPE].includes(this.smartCostType);
return [CO2_TYPE, PRICE_DYNAMIC_TYPE, PRICE_FORECAST_TYPE].includes(this.smartCostType);
},
gridImport: function () {
return Math.max(0, this.gridPower);

View file

@ -114,6 +114,7 @@ export default {
props: {
smartCostLimit: Number,
smartCostType: String,
tariffGrid: Number,
currency: String,
},
data: function () {
@ -241,6 +242,11 @@ export default {
this.updateTariff();
}
},
tariffGrid() {
if (this.isModalVisible) {
this.updateTariff();
}
},
smartCostLimit(limit) {
this.selectedSmartCostLimit = limit;
},

View file

@ -6,6 +6,7 @@ export const UNITS = [KM, MILES];
export const CO2_TYPE = "co2";
export const PRICE_DYNAMIC_TYPE = "pricedynamic";
export const PRICE_FORECAST_TYPE = "priceforecast";
const MILES_FACTOR = 0.6213711922;

View file

@ -147,7 +147,7 @@ func (site *Site) GetTariff(tariff string) api.Tariff {
// prio 0: manually set planner tariff
return site.tariffs.Planner
case site.tariffs.Grid != nil && site.tariffs.Grid.Type() == api.TariffTypePriceDynamic:
case site.tariffs.Grid != nil && site.tariffs.Grid.Type() == api.TariffTypePriceForecast:
// prio 1: dynamic grid tariff
return site.tariffs.Grid

View file

@ -194,6 +194,13 @@ tariffs:
# securitytoken: # api token
# charges: # optional, additional charges per kWh
# tax: # optional, additional tax (0.1 for 10%)
# type: custom # price from a plugin source; see https://docs.evcc.io/docs/reference/plugins
# price:
# source: http
# uri: https://example.org/price.json
# jq: .price.current
feedin:
# rate for feeding excess (pv) energy to the grid
type: fixed

View file

@ -99,5 +99,5 @@ func (t *Awattar) Rates() (api.Rates, error) {
// Type implements the api.Tariff interface
func (t *Awattar) Type() api.TariffType {
return api.TariffTypePriceDynamic
return api.TariffTypePriceForecast
}

View file

@ -112,5 +112,5 @@ func (t *Elering) Rates() (api.Rates, error) {
// Type implements the api.Tariff interface
func (t *Elering) Type() api.TariffType {
return api.TariffTypePriceDynamic
return api.TariffTypePriceForecast
}

View file

@ -109,5 +109,5 @@ func (t *Energinet) Rates() (api.Rates, error) {
// Type implements the api.Tariff interface
func (t *Energinet) Type() api.TariffType {
return api.TariffTypePriceDynamic
return api.TariffTypePriceForecast
}

View file

@ -133,7 +133,7 @@ func (t *Fixed) Rates() (api.Rates, error) {
// Type implements the api.Tariff interface
func (t *Fixed) Type() api.TariffType {
if t.dynamic {
return api.TariffTypePriceDynamic
return api.TariffTypePriceForecast
}
return api.TariffTypePriceStatic
}

View file

@ -110,5 +110,5 @@ func (t *Octopus) Rates() (api.Rates, error) {
// Type implements the api.Tariff interface
func (t *Octopus) Type() api.TariffType {
return api.TariffTypePriceDynamic
return api.TariffTypePriceForecast
}

68
tariff/tariff.go Normal file
View file

@ -0,0 +1,68 @@
package tariff
import (
"fmt"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/provider"
"github.com/evcc-io/evcc/util"
"github.com/jinzhu/now"
)
type Tariff struct {
*embed
priceG func() (float64, error)
}
var _ api.Tariff = (*Tariff)(nil)
func init() {
registry.Add(api.Custom, NewConfigurableFromConfig)
}
func NewConfigurableFromConfig(other map[string]interface{}) (api.Tariff, error) {
var cc struct {
embed `mapstructure:",squash"`
Price provider.Config
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
priceG, err := provider.NewFloatGetterFromConfig(cc.Price)
if err != nil {
return nil, fmt.Errorf("price: %w", err)
}
t := &Tariff{
embed: &cc.embed,
priceG: priceG,
}
return t, nil
}
// Rates implements the api.Tariff interface
func (t *Tariff) Rates() (api.Rates, error) {
price, err := t.priceG()
if err != nil {
return nil, err
}
res := api.Rates{
{
Start: now.BeginningOfHour(),
End: now.BeginningOfHour().Add(48 * time.Hour),
Price: t.totalPrice(price),
},
}
return res, nil
}
// Type implements the api.Tariff interface
func (t *Tariff) Type() api.TariffType {
return api.TariffTypePriceDynamic
}

View file

@ -140,5 +140,5 @@ func (t *Tibber) Rates() (api.Rates, error) {
// Type implements the api.Tariff interface
func (t *Tibber) Type() api.TariffType {
return api.TariffTypePriceDynamic
return api.TariffTypePriceForecast
}