Ctrl K
ComunidadGuías…

tariff/smartenergy.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package tariff

import (
	"slices"
	"sync"
	"time"

	"github.com/cenkalti/backoff/v4"
	"github.com/evcc-io/evcc/api"
	"github.com/evcc-io/evcc/tariff/smartenergy"
	"github.com/evcc-io/evcc/util"
	"github.com/evcc-io/evcc/util/request"
)

type SmartEnergy struct {
	*embed
	log  *util.Logger
	data *util.Monitor[api.Rates]
}

var _ api.Tariff = (*SmartEnergy)(nil)

func init() {
	registry.Add("smartenergy", NewSmartEnergyFromConfig)
}

func NewSmartEnergyFromConfig(other map[string]any) (api.Tariff, error) {
	var cc struct {
		embed `mapstructure:",squash"`
	}

	if err := util.DecodeOther(other, &cc); err != nil {
		return nil, err
	}

	if err := cc.init(); err != nil {
		return nil, err
	}

	t := &SmartEnergy{
		embed: &cc.embed,
		log:   util.NewLogger("smartenergy"),
		data:  util.NewMonitor[api.Rates](2 * time.Hour),
	}

	return runOrError(t)
}

func (t *SmartEnergy) run(done chan error) {
	var once sync.Once
	client := request.NewHelper(t.log)

	for tick := time.Tick(time.Hour); ; <-tick {
		var res smartenergy.Prices

		if err := backoff.Retry(func() error {
			return backoffPermanentError(client.GetJSON(smartenergy.URI, &res))
		}, bo()); err != nil {
			if reportError(&once, done, err) {
				return
			}

			t.log.ERROR.Println(err)
			continue
		}

		data := make(api.Rates, 0, len(res.Data))
		for _, r := range res.Data {
			if r.Date.Minute() != 0 {
				continue
			}

			ar := api.Rate{
				Start: r.Date.Local(),
				End:   r.Date.Add(time.Hour).Local(),
				Value: t.totalPrice(r.Value/100, r.Date),
			}
			data = append(data, ar)
		}

		mergeRates(t.data, data)
		once.Do(func() { close(done) })
	}
}

// Rates implements the api.Tariff interface
func (t *SmartEnergy) Rates() (api.Rates, error) {
	var res api.Rates
	err := t.data.GetFunc(func(val api.Rates) {
		res = slices.Clone(val)
	})
	return res, err
}

// Type implements the api.Tariff interface
func (t *SmartEnergy) Type() api.TariffType {
	return api.TariffTypePriceForecast
}