Skip to content

Commit 44a4e38

Browse files
committed
Add support for variable spot price duration
Signed-off-by: Jacob Laursen <[email protected]>
1 parent 0bf8a7d commit 44a4e38

File tree

6 files changed

+143
-63
lines changed

6 files changed

+143
-63
lines changed

bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/provider/ElectricityPriceProvider.java

+6-10
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ private void refreshElectricityPrices() {
144144
try {
145145
Set<ElectricityPriceListener> spotPricesUpdatedListeners = new HashSet<>();
146146
boolean spotPricesSubscribed = false;
147-
long numberOfFutureSpotPrices = 0;
147+
boolean arePricesFullyCached = true;
148148

149149
for (Entry<Subscription, Set<ElectricityPriceListener>> subscriptionListener : subscriptionToListeners
150150
.entrySet()) {
@@ -157,11 +157,10 @@ private void refreshElectricityPrices() {
157157
if (pricesUpdated) {
158158
spotPricesUpdatedListeners.addAll(listeners);
159159
}
160-
long numberOfFutureSpotPricesForSubscription = getSpotPriceSubscriptionDataCache(subscription)
161-
.getNumberOfFuturePrices();
162-
if (numberOfFutureSpotPrices == 0
163-
|| numberOfFutureSpotPricesForSubscription < numberOfFutureSpotPrices) {
164-
numberOfFutureSpotPrices = numberOfFutureSpotPricesForSubscription;
160+
boolean arePricesFullyCachedForSubscription = getSpotPriceSubscriptionDataCache(subscription)
161+
.arePricesFullyCached();
162+
if (!arePricesFullyCachedForSubscription) {
163+
arePricesFullyCached = false;
165164
}
166165
}
167166
updateCurrentPrices(subscription);
@@ -171,10 +170,7 @@ private void refreshElectricityPrices() {
171170
reschedulePriceUpdateJob();
172171

173172
if (spotPricesSubscribed) {
174-
LocalTime now = LocalTime.now(NORD_POOL_TIMEZONE);
175-
176-
if (numberOfFutureSpotPrices >= 13 || (numberOfFutureSpotPrices == 12
177-
&& now.isAfter(DAILY_REFRESH_TIME_CET.minusHours(1)) && now.isBefore(DAILY_REFRESH_TIME_CET))) {
173+
if (arePricesFullyCached) {
178174
spotPricesUpdatedListeners.forEach(listener -> listener.onDayAheadAvailable());
179175
retryPolicy = RetryPolicyFactory.atFixedTime(DAILY_REFRESH_TIME_CET, NORD_POOL_TIMEZONE);
180176
} else {

bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/provider/cache/DatahubPriceSubscriptionCache.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import static org.openhab.binding.energidataservice.internal.EnergiDataServiceBindingConstants.*;
1616

1717
import java.time.Clock;
18+
import java.time.Duration;
1819
import java.time.LocalDateTime;
1920
import java.time.temporal.ChronoUnit;
2021
import java.util.Collection;
@@ -45,7 +46,7 @@ public DatahubPriceSubscriptionCache() {
4546
}
4647

4748
public DatahubPriceSubscriptionCache(Clock clock) {
48-
super(clock, MAX_CACHE_SIZE);
49+
super(clock, Duration.ofHours(1));
4950
}
5051

5152
/**

bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/provider/cache/ElectricityPriceSubscriptionCache.java

+17-20
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616

1717
import java.math.BigDecimal;
1818
import java.time.Clock;
19+
import java.time.Duration;
1920
import java.time.Instant;
2021
import java.time.temporal.ChronoUnit;
2122
import java.util.HashMap;
2223
import java.util.Map;
23-
import java.util.concurrent.ConcurrentHashMap;
24+
import java.util.NavigableMap;
25+
import java.util.concurrent.ConcurrentSkipListMap;
2426

2527
import org.eclipse.jdt.annotation.NonNullByDefault;
2628
import org.eclipse.jdt.annotation.Nullable;
2729

2830
/**
2931
* Electricity price specific {@link SubscriptionDataCache} implementation.
32+
* All price durations must be the same.
3033
*
3134
* @author Jacob Laursen - Initial contribution
3235
*/
@@ -35,13 +38,16 @@ public abstract class ElectricityPriceSubscriptionCache<R> implements Subscripti
3538

3639
public static final int NUMBER_OF_HISTORIC_HOURS = 24;
3740

38-
protected final Map<Instant, BigDecimal> priceMap;
41+
protected final NavigableMap<Instant, BigDecimal> priceMap;
3942

4043
protected final Clock clock;
4144

42-
protected ElectricityPriceSubscriptionCache(Clock clock, int initialCapacity) {
45+
protected final Duration priceDuration;
46+
47+
protected ElectricityPriceSubscriptionCache(Clock clock, Duration priceDuration) {
4348
this.clock = clock.withZone(NORD_POOL_TIMEZONE);
44-
this.priceMap = new ConcurrentHashMap<>(initialCapacity);
49+
this.priceDuration = priceDuration;
50+
this.priceMap = new ConcurrentSkipListMap<>();
4551
}
4652

4753
@Override
@@ -68,19 +74,11 @@ public Map<Instant, BigDecimal> get() {
6874
*/
6975
@Override
7076
public @Nullable BigDecimal get(Instant time) {
71-
return priceMap.get(getHourStart(time));
72-
}
73-
74-
/**
75-
* Get number of future prices including current hour.
76-
*
77-
* @return number of future prices
78-
*/
79-
@Override
80-
public long getNumberOfFuturePrices() {
81-
Instant currentHourStart = getCurrentHourStart();
82-
83-
return priceMap.entrySet().stream().filter(p -> !p.getKey().isBefore(currentHourStart)).count();
77+
Map.Entry<Instant, BigDecimal> entry = priceMap.floorEntry(time);
78+
if (entry != null && !time.isAfter(entry.getKey().plus(priceDuration))) {
79+
return entry.getValue();
80+
}
81+
return null;
8482
}
8583

8684
/**
@@ -94,9 +92,8 @@ public boolean areHistoricPricesCached() {
9492
}
9593

9694
protected boolean arePricesCached(Instant end) {
97-
for (Instant hourStart = getFirstHourStart(); hourStart.compareTo(end) <= 0; hourStart = hourStart.plus(1,
98-
ChronoUnit.HOURS)) {
99-
if (priceMap.get(hourStart) == null) {
95+
for (Instant start = getFirstHourStart(); start.compareTo(end) <= 0; start = start.plus(priceDuration)) {
96+
if (priceMap.get(start) == null) {
10097
return false;
10198
}
10299
}

bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/provider/cache/SpotPriceSubscriptionCache.java

+11-10
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
import java.math.BigDecimal;
1818
import java.time.Clock;
19+
import java.time.Duration;
1920
import java.time.Instant;
2021
import java.time.LocalDate;
2122
import java.time.LocalTime;
2223
import java.time.ZonedDateTime;
23-
import java.time.temporal.ChronoUnit;
2424

2525
import org.eclipse.jdt.annotation.NonNullByDefault;
2626
import org.openhab.binding.energidataservice.internal.api.dto.ElspotpriceRecord;
@@ -34,16 +34,14 @@
3434
@NonNullByDefault
3535
public class SpotPriceSubscriptionCache extends ElectricityPriceSubscriptionCache<ElspotpriceRecord[]> {
3636

37-
private static final int MAX_CACHE_SIZE = 24 + 11 + NUMBER_OF_HISTORIC_HOURS;
38-
3937
private final SpotPriceSubscription subscription;
4038

4139
public SpotPriceSubscriptionCache(SpotPriceSubscription subscription) {
42-
this(subscription, Clock.systemDefaultZone());
40+
this(subscription, Clock.systemDefaultZone(), Duration.ofHours(1));
4341
}
4442

45-
public SpotPriceSubscriptionCache(SpotPriceSubscription subscription, Clock clock) {
46-
super(clock, MAX_CACHE_SIZE);
43+
public SpotPriceSubscriptionCache(SpotPriceSubscription subscription, Clock clock, Duration priceDuration) {
44+
super(clock, priceDuration);
4745
this.subscription = subscription;
4846
}
4947

@@ -79,12 +77,15 @@ public boolean put(ElspotpriceRecord[] records) {
7977
* @return true if spot prices are fully cached
8078
*/
8179
public boolean arePricesFullyCached() {
82-
Instant end = ZonedDateTime.of(LocalDate.now(clock), LocalTime.of(23, 0), NORD_POOL_TIMEZONE).toInstant();
83-
LocalTime now = LocalTime.now(clock);
84-
if (now.isAfter(DAILY_REFRESH_TIME_CET)) {
85-
end = end.plus(24, ChronoUnit.HOURS);
80+
LocalDate date = LocalDate.now(clock);
81+
82+
if (LocalTime.now(clock).isAfter(DAILY_REFRESH_TIME_CET)) {
83+
date = date.plusDays(1);
8684
}
8785

86+
Instant end = ZonedDateTime.of(date.plusDays(1), LocalTime.MIDNIGHT, NORD_POOL_TIMEZONE).minus(priceDuration)
87+
.toInstant();
88+
8889
return arePricesCached(end);
8990
}
9091
}

bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/provider/cache/SubscriptionDataCache.java

-7
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,6 @@ public interface SubscriptionDataCache<R> {
5656
*/
5757
void flush();
5858

59-
/**
60-
* Get the number of future prices in the cache.
61-
*
62-
* @return number of cached future prices
63-
*/
64-
long getNumberOfFuturePrices();
65-
6659
/**
6760
* Check if all required historic values are cached, considering
6861
* {@link ElectricityPriceSubscriptionCache#NUMBER_OF_HISTORIC_HOURS}.

0 commit comments

Comments
 (0)