Add configurable custom tariff (#10306)
This commit is contained in:
parent
3b11d0e253
commit
7ad03ecc34
14 changed files with 104 additions and 17 deletions
|
|
@ -8,5 +8,6 @@ const (
|
|||
_ TariffType = iota
|
||||
TariffTypePriceStatic
|
||||
TariffTypePriceDynamic
|
||||
TariffTypePriceForecast
|
||||
TariffTypeCo2
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
68
tariff/tariff.go
Normal 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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue