Solcast: limit api calls by time of day (#20696)
Some checks failed
Release / call-build-workflow (push) Has been cancelled
Release / Publish Docker :release (push) Has been cancelled
Release / Github & APT (push) Has been cancelled
Release / Demo (push) Has been cancelled
Release / Hassio Addon (push) Has been cancelled

This commit is contained in:
TomF79 2025-04-22 13:50:26 +02:00 • committed by GitHub
parent 049075043b
commit 36330ac2cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 69 additions and 5 deletions

View file

@ -18,9 +18,10 @@ import (
type Solcast struct {
*request.Helper
log *util.Logger
site string
data *util.Monitor[api.Rates]
log *util.Logger
site string
fromTo FromTo
data *util.Monitor[api.Rates]
}
var _ api.Tariff = (*Solcast)(nil)
@ -34,6 +35,7 @@ func NewSolcastFromConfig(other map[string]interface{}) (api.Tariff, error) {
Site string
Token string
Interval time.Duration
FromTo `mapstructure:",squash"`
}{
Interval: 3 * time.Hour,
}
@ -56,6 +58,7 @@ func NewSolcastFromConfig(other map[string]interface{}) (api.Tariff, error) {
log: log,
site: cc.Site,
Helper: request.NewHelper(log),
fromTo: cc.FromTo,
data: util.NewMonitor[api.Rates](2 * cc.Interval),
}
@ -71,8 +74,16 @@ func NewSolcastFromConfig(other map[string]interface{}) (api.Tariff, error) {
func (t *Solcast) run(interval time.Duration, done chan error) {
var once sync.Once
// don't exceed 10 requests per 24h
for ; true; <-time.Tick(interval) {
// ensure we don't run when not needed, but execute once at startup
select {
case <-t.data.Done():
if !t.fromTo.IsActive(time.Now().Hour()) {
continue
}
default:
}
var res solcast.Forecasts
if err := backoff.Retry(func() error {
@ -80,7 +91,6 @@ func (t *Solcast) run(interval time.Duration, done chan error) {
return backoffPermanentError(t.GetJSON(uri, &res))
}, bo()); err != nil {
once.Do(func() { done <- err })
t.log.ERROR.Println(err)
continue
}

View file

@ -12,3 +12,13 @@ func (t Typed) Name() string {
}
return t.Type
}
type FromTo struct {
From, To int
}
func (ft FromTo) IsActive(hour int) bool {
return ft.From == 0 && ft.To == 0 ||
ft.From < ft.To && ft.From <= hour && hour <= ft.To ||
ft.From > ft.To && (ft.From <= hour || hour <= ft.To)
}

34
tariff/types_test.go Normal file
View file

@ -0,0 +1,34 @@
package tariff
import (
"testing"
"time"
"github.com/benbjohnson/clock"
"github.com/stretchr/testify/assert"
)
func TestFromTo(t *testing.T) {
tc := []struct {
from, to, now int
active bool
}{
{0, 0, 0, true},
{1, 2, 1, true},
{1, 2, 2, true},
{1, 2, 0, false},
{1, 2, 3, false},
{22, 2, 21, false},
{22, 2, 22, true},
{22, 2, 2, true},
{22, 2, 3, false},
}
for _, tc := range tc {
clock := clock.NewMock()
clock.Add(time.Duration(tc.now) * time.Hour)
ft := FromTo{tc.from, tc.to}
assert.Equal(t, tc.active, ft.IsActive(tc.now), "expected %v")
}
}

View file

@ -18,6 +18,16 @@ params:
en: Solcast API Token
de: Solcast API Token
required: true
- name: from
help:
en: Start time of data retrieval, specified in full hours, e.g. "6"
de: Startzeit der Datenabrufe, Angabe in vollen Stunden, z.B "6"
advanced: true
- name: to
help:
en: End time of data retrieval, specified in full hours, e.g. "20"
de: Endzeit der Datenabrufe, Angabe in vollen Stunden, z.B "20"
advanced: true
- name: interval
default: 3h
advanced: true