Introduce a trigger channel to announce the availability of day-ahead prices (#16704)

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Jacob Laursen 2024-05-10 17:09:27 +02:00 committed by Ciprian Pascu
parent 29cecb756e
commit 1e63944801
8 changed files with 74 additions and 4 deletions

View File

@ -170,6 +170,14 @@ A persistence configuration is required for this channel.
Please note that the CO₂ emission channels only apply to Denmark. Please note that the CO₂ emission channels only apply to Denmark.
These channels will not be updated when the configured price area is not DK1 or DK2. These channels will not be updated when the configured price area is not DK1 or DK2.
#### Trigger Channels
Advanced channel `event` can trigger the following events:
| Event | Description |
|----------------------|--------------------------------|
| DAY_AHEAD_AVAILABLE | Day-ahead prices are available |
## Thing Actions ## Thing Actions
Thing actions can be used to perform calculations as well as import prices directly into rules without relying on persistence. Thing actions can be used to perform calculations as well as import prices directly into rules without relying on persistence.
@ -561,3 +569,36 @@ console.log("Spot price two hours from now: " + price);
::: :::
:::: ::::
### Trigger Channel Example
:::: tabs
::: tab DSL
```javascript
rule "Day-ahead event"
when
Channel 'energidataservice:service:energidataservice:electricity#event' triggered 'DAY_AHEAD_AVAILABLE'
then
logInfo("Day-ahead", "Day-ahead prices for the next day are now available")
end
```
:::
::: tab JavaScript
```javascript
rules.when()
.channel('energidataservice:service:energidataservice:electricity#event').triggered('DAY_AHEAD_AVAILABLE')
.then(event =>
{
console.log('Day-ahead prices for the next day are now available');
})
.build("Day-ahead event");
```
:::
::::

View File

@ -56,6 +56,7 @@ public class EnergiDataServiceBindingConstants {
+ ChannelUID.CHANNEL_GROUP_SEPARATOR + "co2-emission-prognosis"; + ChannelUID.CHANNEL_GROUP_SEPARATOR + "co2-emission-prognosis";
public static final String CHANNEL_CO2_EMISSION_REALTIME = CHANNEL_GROUP_ELECTRICITY public static final String CHANNEL_CO2_EMISSION_REALTIME = CHANNEL_GROUP_ELECTRICITY
+ ChannelUID.CHANNEL_GROUP_SEPARATOR + "co2-emission-realtime"; + ChannelUID.CHANNEL_GROUP_SEPARATOR + "co2-emission-realtime";
public static final String CHANNEL_EVENT = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR + "event";
public static final Set<String> ELECTRICITY_CHANNELS = Set.of(CHANNEL_SPOT_PRICE, CHANNEL_GRID_TARIFF, public static final Set<String> ELECTRICITY_CHANNELS = Set.of(CHANNEL_SPOT_PRICE, CHANNEL_GRID_TARIFF,
CHANNEL_SYSTEM_TARIFF, CHANNEL_TRANSMISSION_GRID_TARIFF, CHANNEL_ELECTRICITY_TAX, CHANNEL_SYSTEM_TARIFF, CHANNEL_TRANSMISSION_GRID_TARIFF, CHANNEL_ELECTRICITY_TAX,
@ -67,6 +68,9 @@ public class EnergiDataServiceBindingConstants {
public static final String PROPERTY_LAST_CALL = "lastCall"; public static final String PROPERTY_LAST_CALL = "lastCall";
public static final String PROPERTY_NEXT_CALL = "nextCall"; public static final String PROPERTY_NEXT_CALL = "nextCall";
// List of all events
public static final String EVENT_DAY_AHEAD_AVAILABLE = "DAY_AHEAD_AVAILABLE";
// List of supported currencies // List of supported currencies
public static final Currency CURRENCY_DKK = Currency.getInstance("DKK"); public static final Currency CURRENCY_DKK = Currency.getInstance("DKK");
public static final Currency CURRENCY_EUR = Currency.getInstance("EUR"); public static final Currency CURRENCY_EUR = Currency.getInstance("EUR");

View File

@ -239,8 +239,9 @@ public class EnergiDataServiceHandler extends BaseThingHandler {
private void refreshElectricityPrices() { private void refreshElectricityPrices() {
RetryStrategy retryPolicy; RetryStrategy retryPolicy;
try { try {
boolean spotPricesDownloaded = false;
if (isLinked(CHANNEL_SPOT_PRICE)) { if (isLinked(CHANNEL_SPOT_PRICE)) {
downloadSpotPrices(); spotPricesDownloaded = downloadSpotPrices();
} }
for (DatahubTariff datahubTariff : DatahubTariff.values()) { for (DatahubTariff datahubTariff : DatahubTariff.values()) {
@ -259,6 +260,9 @@ public class EnergiDataServiceHandler extends BaseThingHandler {
if (numberOfFutureSpotPrices >= 13 || (numberOfFutureSpotPrices == 12 if (numberOfFutureSpotPrices >= 13 || (numberOfFutureSpotPrices == 12
&& now.isAfter(DAILY_REFRESH_TIME_CET.minusHours(1)) && now.isBefore(DAILY_REFRESH_TIME_CET))) { && now.isAfter(DAILY_REFRESH_TIME_CET.minusHours(1)) && now.isBefore(DAILY_REFRESH_TIME_CET))) {
if (spotPricesDownloaded) {
triggerChannel(CHANNEL_EVENT, EVENT_DAY_AHEAD_AVAILABLE);
}
retryPolicy = RetryPolicyFactory.atFixedTime(DAILY_REFRESH_TIME_CET, NORD_POOL_TIMEZONE); retryPolicy = RetryPolicyFactory.atFixedTime(DAILY_REFRESH_TIME_CET, NORD_POOL_TIMEZONE);
} else { } else {
logger.warn("Spot prices are not available, retry scheduled (see details in Thing properties)"); logger.warn("Spot prices are not available, retry scheduled (see details in Thing properties)");
@ -287,10 +291,10 @@ public class EnergiDataServiceHandler extends BaseThingHandler {
reschedulePriceRefreshJob(retryPolicy); reschedulePriceRefreshJob(retryPolicy);
} }
private void downloadSpotPrices() throws InterruptedException, DataServiceException { private boolean downloadSpotPrices() throws InterruptedException, DataServiceException {
if (cacheManager.areSpotPricesFullyCached()) { if (cacheManager.areSpotPricesFullyCached()) {
logger.debug("Cached spot prices still valid, skipping download."); logger.debug("Cached spot prices still valid, skipping download.");
return; return false;
} }
DateQueryParameter start; DateQueryParameter start;
if (cacheManager.areHistoricSpotPricesCached()) { if (cacheManager.areHistoricSpotPricesCached()) {
@ -307,6 +311,7 @@ public class EnergiDataServiceHandler extends BaseThingHandler {
} finally { } finally {
updateProperties(properties); updateProperties(properties);
} }
return true;
} }
private void downloadTariffs(DatahubTariff datahubTariff) throws InterruptedException, DataServiceException { private void downloadTariffs(DatahubTariff datahubTariff) throws InterruptedException, DataServiceException {

View File

@ -81,6 +81,8 @@ channel-type.energidataservice.co2-emission.label = CO₂ Emission
channel-type.energidataservice.co2-emission.description = CO₂ emission in g/kWh. channel-type.energidataservice.co2-emission.description = CO₂ emission in g/kWh.
channel-type.energidataservice.datahub-price.label = Datahub Price channel-type.energidataservice.datahub-price.label = Datahub Price
channel-type.energidataservice.datahub-price.description = Datahub price. channel-type.energidataservice.datahub-price.description = Datahub price.
channel-type.energidataservice.event.label = Event
channel-type.energidataservice.event.description = Event triggered
channel-type.energidataservice.spot-price.label = Spot Price channel-type.energidataservice.spot-price.label = Spot Price
channel-type.energidataservice.spot-price.description = Spot price. channel-type.energidataservice.spot-price.description = Spot price.

View File

@ -40,6 +40,7 @@
<label>CO₂ Emission Realtime</label> <label>CO₂ Emission Realtime</label>
<description>Near up-to-date history for CO₂ emission from electricity consumed in Denmark in g/kWh.</description> <description>Near up-to-date history for CO₂ emission from electricity consumed in Denmark in g/kWh.</description>
</channel> </channel>
<channel id="event" typeId="event"/>
</channels> </channels>
</channel-group-type> </channel-group-type>

View File

@ -29,4 +29,15 @@
<state readOnly="true" pattern="%.1f %unit%"></state> <state readOnly="true" pattern="%.1f %unit%"></state>
</channel-type> </channel-type>
<channel-type id="event" advanced="true">
<kind>trigger</kind>
<label>Event</label>
<description>Event triggered</description>
<event>
<options>
<option value="DAY_AHEAD_AVAILABLE">Day-ahead prices are available</option>
</options>
</event>
</channel-type>
</thing:thing-descriptions> </thing:thing-descriptions>

View File

@ -14,7 +14,7 @@
</channel-groups> </channel-groups>
<properties> <properties>
<property name="thingTypeVersion">5</property> <property name="thingTypeVersion">6</property>
</properties> </properties>
<config-description-ref uri="thing-type:energidataservice:service"/> <config-description-ref uri="thing-type:energidataservice:service"/>

View File

@ -78,6 +78,12 @@
</add-channel> </add-channel>
</instruction-set> </instruction-set>
<instruction-set targetVersion="6">
<add-channel id="event" groupIds="electricity">
<type>energidataservice:event</type>
</add-channel>
</instruction-set>
</thing-type> </thing-type>
</update:update-descriptions> </update:update-descriptions>