183 lines
3.2 KiB
Go
183 lines
3.2 KiB
Go
package energy
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/amigan/energyd/pkg/isoclient"
|
|
"github.com/lucasb-eyer/go-colorful"
|
|
"github.com/mazznoer/colorgrad"
|
|
)
|
|
|
|
type Energy struct {
|
|
iso isoclient.Client
|
|
}
|
|
|
|
type LoadProfile struct {
|
|
Time time.Time
|
|
Current int
|
|
Peak int
|
|
Lowest int
|
|
PeakHr int
|
|
LowestHr int
|
|
|
|
PctPeak int
|
|
HoursAway int
|
|
HighFuel string
|
|
MarginalFuels MarginalFuels
|
|
}
|
|
|
|
type MarginalFuels []string
|
|
|
|
func (mf MarginalFuels) String() string {
|
|
return strings.Join(mf, ", ")
|
|
}
|
|
|
|
func (e *Energy) Compute() error {
|
|
ic := e.iso
|
|
|
|
load, err := ic.GetCurrentLoad()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
gphd, err := ic.GetHourlyLoadForecast()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fm, err := ic.GetGenFuelMixes()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
lp := LoadProfile{
|
|
Time: load.BeginDate,
|
|
Current: int(load.LoadMW),
|
|
LowestHr: -1,
|
|
}
|
|
|
|
if len(fm) > 0 {
|
|
highGen := int(fm[0].GenMW)
|
|
highFuel := fm[0]
|
|
|
|
for _, mix := range fm {
|
|
if int(mix.GenMW) > highGen {
|
|
highGen = int(mix.GenMW)
|
|
highFuel = mix
|
|
}
|
|
|
|
if mix.Marginal {
|
|
lp.MarginalFuels = append(lp.MarginalFuels, mix.FuelCategory)
|
|
}
|
|
}
|
|
|
|
lp.HighFuel = highFuel.FuelCategory
|
|
}
|
|
|
|
for h, hf := range gphd.HourlyLoadForecast {
|
|
if int(hf.LoadMW) > lp.Peak {
|
|
lp.Peak = int(hf.LoadMW)
|
|
lp.PeakHr = h
|
|
}
|
|
|
|
if int(hf.LoadMW) < lp.Lowest || lp.LowestHr == -1 {
|
|
lp.LowestHr = h
|
|
lp.Lowest = int(hf.LoadMW)
|
|
}
|
|
}
|
|
|
|
hour := time.Now().Hour()
|
|
lp.PctPeak = int(float32(load.LoadMW/float32(lp.Peak)) * 100)
|
|
lp.HoursAway = int(math.Abs(float64(hour) - float64(lp.PeakHr)))
|
|
fmt.Println(lp.String())
|
|
|
|
return nil
|
|
}
|
|
|
|
type Colors struct {
|
|
Mix [2]colorful.Color
|
|
Peak [2]colorful.Color
|
|
}
|
|
|
|
func vaporwavePalette() []string {
|
|
return []string{
|
|
"#01cdfe", // blue
|
|
"#05ffa1", // green
|
|
"#fffb96", // gold
|
|
"#ff71ce", // pinkred
|
|
"#b967ff", // purple
|
|
}
|
|
}
|
|
|
|
func outrunPalette() []string {
|
|
return []string{
|
|
"#2de2e6", // blue
|
|
"#00ff1b", // green
|
|
"#ff6c11", // gold
|
|
"#ff3864", // pinkred
|
|
"#7930ff", // purple
|
|
}
|
|
}
|
|
|
|
func (lp *LoadProfile) PeakScaleColors() []string {
|
|
var scale []string
|
|
palette := outrunPalette()
|
|
|
|
nowHr := time.Now().Hour() // XXX: get this from lp
|
|
|
|
//if lp.HoursAway >
|
|
|
|
_, _ = palette, nowHr
|
|
|
|
return scale
|
|
}
|
|
|
|
func (lp *LoadProfile) String() string {
|
|
return fmt.Sprintf("%s\tC: %d\tP: %d\tL: %d\tPeakHr: %d\tLowestHr: %d\t%%Pk: %d\tHrAway: %d\tPkFuel: %s\tMarginal: %s",
|
|
lp.Time.String(), lp.Current, lp.Peak, lp.Lowest, lp.PeakHr, lp.LowestHr, lp.PctPeak, lp.HoursAway, lp.HighFuel, lp.MarginalFuels)
|
|
}
|
|
|
|
func (lp *LoadProfile) Colors() Colors {
|
|
c := Colors{}
|
|
|
|
peak, err := colorgrad.NewGradient().Domain(float64(lp.Lowest), float64(lp.Peak)).HtmlColors(lp.PeakScaleColors()...).Build()
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
c.Peak[0] = peak.At(float64(time.Now().Hour()))
|
|
|
|
return c
|
|
}
|
|
|
|
func (e *Energy) Go(ctx context.Context) {
|
|
tick := time.NewTicker(time.Minute * 15)
|
|
err := e.Compute()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case <-tick.C:
|
|
err := e.Compute()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
case <-ctx.Done():
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func New(ic isoclient.Client) *Energy {
|
|
return &Energy{
|
|
iso: ic,
|
|
}
|
|
}
|