Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tariffs: publish forecast #18013

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 22 additions & 29 deletions core/keys/site.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
package keys

const (
Aux = "aux"
AuxPower = "auxPower"
Currency = "currency"
GreenShareHome = "greenShareHome"
GreenShareLoadpoints = "greenShareLoadpoints"
GridConfigured = "gridConfigured"
GridCurrents = "gridCurrents"
GridEnergy = "gridEnergy"
GridPower = "gridPower"
GridPowers = "gridPowers"
HomePower = "homePower"
PrioritySoc = "prioritySoc"
Pv = "pv"
PvEnergy = "pvEnergy"
PvPower = "pvPower"
ResidualPower = "residualPower"
SiteTitle = "siteTitle"
SmartCostType = "smartCostType"
Statistics = "statistics"
TariffCo2 = "tariffCo2"
TariffCo2Home = "tariffCo2Home"
TariffCo2Loadpoints = "tariffCo2Loadpoints"
TariffFeedIn = "tariffFeedIn"
TariffGrid = "tariffGrid"
TariffPriceHome = "tariffPriceHome"
TariffPriceLoadpoints = "tariffPriceLoadpoints"
Vehicles = "vehicles"
Circuits = "circuits"
Ext = "ext"
Aux = "aux"
AuxPower = "auxPower"
Currency = "currency"
GreenShare = "greenShare"
GridConfigured = "gridConfigured"
GridCurrents = "gridCurrents"
GridEnergy = "gridEnergy"
GridPower = "gridPower"
GridPowers = "gridPowers"
HomePower = "homePower"
PrioritySoc = "prioritySoc"
Pv = "pv"
PvEnergy = "pvEnergy"
PvPower = "pvPower"
ResidualPower = "residualPower"
SiteTitle = "siteTitle"
SmartCostType = "smartCostType"
Statistics = "statistics"
EffectivePrive = "effectivePrice"
Vehicles = "vehicles"
Circuits = "circuits"
Ext = "ext"

// meters
GridMeter = "gridMeter"
Expand Down
77 changes: 50 additions & 27 deletions core/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ type Site struct {
batteryPower float64 // Battery charge power
batterySoc float64 // Battery soc
batteryMode api.BatteryMode // Battery mode (runtime only, not persisted)

publishCache map[string]any // store last published values to avoid unnecessary republishing
}

// MetersConfig contains the site's meter configuration
Expand Down Expand Up @@ -248,9 +246,8 @@ func (site *Site) Boot(log *util.Logger, loadpoints []*Loadpoint, tariffs *tarif
// NewSite creates a Site with sane defaults
func NewSite() *Site {
lp := &Site{
log: util.NewLogger("site"),
publishCache: make(map[string]any),
Voltage: 230, // V
log: util.NewLogger("site"),
Voltage: 230, // V
}

return lp
Expand Down Expand Up @@ -424,16 +421,6 @@ func (site *Site) publish(key string, val interface{}) {
site.uiChan <- util.Param{Key: key, Val: val}
}

// publishDelta deduplicates messages before publishing
func (site *Site) publishDelta(key string, val interface{}) {
if v, ok := site.publishCache[key]; ok && v == val {
return
}

site.publishCache[key] = val
site.publish(key, val)
}

// updatePvMeters updates pv meters. All measurements are optional.
func (site *Site) updatePvMeters() {
if len(site.pvMeters) == 0 {
Expand Down Expand Up @@ -862,30 +849,66 @@ func (site *Site) effectiveCo2(greenShare float64) *float64 {
}

func (site *Site) publishTariffs(greenShareHome float64, greenShareLoadpoints float64) {
site.publish(keys.GreenShareHome, greenShareHome)
site.publish(keys.GreenShareLoadpoints, greenShareLoadpoints)
type tarif struct {
Price *float64 `json:"price,omitempty"`
Co2 *float64 `json:"co2,omitempty"`
Forecast []api.Rate `json:"forecast,omitempty"`
}

if gridPrice, err := site.tariffs.CurrentGridPrice(); err == nil {
site.publishDelta(keys.TariffGrid, gridPrice)
var tariffs struct {
Grid tarif `json:"grid,omitempty"`
FeedIn tarif `json:"feedIn,omitempty"`
Co2 tarif `json:"co2,omitempty"`
}
if feedInPrice, err := site.tariffs.CurrentFeedInPrice(); err == nil {
site.publishDelta(keys.TariffFeedIn, feedInPrice)

tariffs.Grid.Forecast = tariff.Forecast(site.tariffs.Grid)
if val, err := site.tariffs.CurrentGridPrice(); err == nil {
tariffs.Grid.Price = &val
}
if co2, err := site.tariffs.CurrentCo2(); err == nil {
site.publishDelta(keys.TariffCo2, co2)
tariffs.FeedIn.Forecast = tariff.Forecast(site.tariffs.FeedIn)
if val, err := site.tariffs.CurrentFeedInPrice(); err == nil {
tariffs.FeedIn.Price = &val
}
// TODO CO2 type
tariffs.Co2.Forecast = tariff.Forecast(site.tariffs.Co2)
if val, err := site.tariffs.CurrentCo2(); err == nil {
tariffs.Co2.Co2 = &val
}

site.publish(keys.Tariffs, tariffs)

type effective struct {
GreenPercent float64 `json:"greenPercent"`
Price *float64 `json:"effectivePrice,omitempty"`
Co2 *float64 `json:"effectiveCo2,omitempty"`
}

share := struct {
Home effective `json:"home"`
Loadpoints effective `json:"loadpoints"`
}{
Home: effective{
GreenPercent: greenShareHome,
},
Loadpoints: effective{
GreenPercent: greenShareLoadpoints,
},
}

if price := site.effectivePrice(greenShareHome); price != nil {
site.publish(keys.TariffPriceHome, price)
share.Home.Price = price
}
if co2 := site.effectiveCo2(greenShareHome); co2 != nil {
site.publish(keys.TariffCo2Home, co2)
share.Home.Co2 = co2
}
if price := site.effectivePrice(greenShareLoadpoints); price != nil {
site.publish(keys.TariffPriceLoadpoints, price)
share.Loadpoints.Price = price
}
if co2 := site.effectiveCo2(greenShareLoadpoints); co2 != nil {
site.publish(keys.TariffCo2Loadpoints, co2)
share.Loadpoints.Co2 = co2
}

site.publish(keys.GreenShare, share)
}

// updateLoadpoints updates all loadpoints' charge power
Expand Down
9 changes: 9 additions & 0 deletions tariff/tariffs.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ type Tariffs struct {
Grid, FeedIn, Co2, Planner api.Tariff
}

func Forecast(t api.Tariff) []api.Rate {
if t != nil && t.Type() == api.TariffTypePriceForecast {
if rr, err := t.Rates(); err == nil {
return rr
}
}
return nil
}

func currentPrice(t api.Tariff) (float64, error) {
if t != nil {
if rr, err := t.Rates(); err == nil {
Expand Down
Loading