Rename price element to price component (#15935)
Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
parent
ff873fff14
commit
b2b7602eee
@ -40,7 +40,7 @@ To obtain the Global Location Number of your grid company:
|
|||||||
|
|
||||||
For customers using electricity for heating, a reduced electricity tax rate may apply after consuming the first 4000 kWh within a year.
|
For customers using electricity for heating, a reduced electricity tax rate may apply after consuming the first 4000 kWh within a year.
|
||||||
When you are entitled to reduced electricity tax, this option should be set.
|
When you are entitled to reduced electricity tax, this option should be set.
|
||||||
This will ensure that thing action calculations use the reduced electricity tax rate when price elements are not explicitly provided.
|
This will ensure that thing action calculations use the reduced electricity tax rate when price components are not explicitly provided.
|
||||||
It will not impact channels, see [Electricity Tax](#electricity-tax) for further information.
|
It will not impact channels, see [Electricity Tax](#electricity-tax) for further information.
|
||||||
|
|
||||||
## Channels
|
## Channels
|
||||||
@ -170,7 +170,7 @@ Historic prices older than 24 hours are removed from the JSON array each hour.
|
|||||||
## Thing Actions
|
## Thing Actions
|
||||||
|
|
||||||
Thing actions can be used to perform calculations as well as import prices directly into rules without deserializing JSON from the [hourly-prices](#hourly-prices) channel.
|
Thing actions can be used to perform calculations as well as import prices directly into rules without deserializing JSON from the [hourly-prices](#hourly-prices) channel.
|
||||||
This is more convenient, much faster, and provides automatic summation of the price elements of interest.
|
This is more convenient, much faster, and provides automatic summation of the price components of interest.
|
||||||
|
|
||||||
Actions use cached data for performing operations.
|
Actions use cached data for performing operations.
|
||||||
Since data is only fetched when an item is linked to a channel, there might not be any cached data available.
|
Since data is only fetched when an item is linked to a channel, there might not be any cached data available.
|
||||||
@ -327,14 +327,14 @@ var price = actions.calculatePrice(now.toInstant(), now.plusHours(4).toInstant,
|
|||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
|--------------------|-----------------------------|--------------------------------------------------------|
|
|--------------------|-----------------------------|--------------------------------------------------------|
|
||||||
| priceElements | `String` | Comma-separated list of price elements to include |
|
| priceComponents | `String` | Comma-separated list of price components to include |
|
||||||
|
|
||||||
**Result:** `Map<Instant, BigDecimal>`
|
**Result:** `Map<Instant, BigDecimal>`
|
||||||
|
|
||||||
The parameter `priceElements` is a case-insensitive comma-separated list of price elements to include in the returned hourly prices.
|
The parameter `priceComponents` is a case-insensitive comma-separated list of price components to include in the returned hourly prices.
|
||||||
These elements can be requested:
|
These components can be requested:
|
||||||
|
|
||||||
| Price element | Description |
|
| Price component | Description |
|
||||||
|-----------------------|-------------------------|
|
|-----------------------|-------------------------|
|
||||||
| SpotPrice | Spot price |
|
| SpotPrice | Spot price |
|
||||||
| NetTariff | Net tariff |
|
| NetTariff | Net tariff |
|
||||||
@ -343,7 +343,7 @@ These elements can be requested:
|
|||||||
| ReducedElectricityTax | Reduced electricity tax |
|
| ReducedElectricityTax | Reduced electricity tax |
|
||||||
| TransmissionNetTariff | Transmission net tariff |
|
| TransmissionNetTariff | Transmission net tariff |
|
||||||
|
|
||||||
Using `null` as parameter returns the total prices including all price elements.
|
Using `null` as parameter returns the total prices including all price components.
|
||||||
If **Reduced Electricity Tax** is set in Thing configuration, `ElectricityTax` will be excluded, otherwise `ReducedElectricityTax`.
|
If **Reduced Electricity Tax** is set in Thing configuration, `ElectricityTax` will be excluded, otherwise `ReducedElectricityTax`.
|
||||||
This logic ensures consistent and comparable results not affected by artifical changes in the rate for electricity tax two times per year.
|
This logic ensures consistent and comparable results not affected by artifical changes in the rate for electricity tax two times per year.
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
|
|
||||||
private @Nullable EnergiDataServiceHandler handler;
|
private @Nullable EnergiDataServiceHandler handler;
|
||||||
|
|
||||||
private enum PriceElement {
|
private enum PriceComponent {
|
||||||
SPOT_PRICE("spotprice", null),
|
SPOT_PRICE("spotprice", null),
|
||||||
NET_TARIFF("nettariff", DatahubTariff.NET_TARIFF),
|
NET_TARIFF("nettariff", DatahubTariff.NET_TARIFF),
|
||||||
SYSTEM_TARIFF("systemtariff", DatahubTariff.SYSTEM_TARIFF),
|
SYSTEM_TARIFF("systemtariff", DatahubTariff.SYSTEM_TARIFF),
|
||||||
@ -69,13 +69,13 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
REDUCED_ELECTRICITY_TAX("reducedelectricitytax", DatahubTariff.REDUCED_ELECTRICITY_TAX),
|
REDUCED_ELECTRICITY_TAX("reducedelectricitytax", DatahubTariff.REDUCED_ELECTRICITY_TAX),
|
||||||
TRANSMISSION_NET_TARIFF("transmissionnettariff", DatahubTariff.TRANSMISSION_NET_TARIFF);
|
TRANSMISSION_NET_TARIFF("transmissionnettariff", DatahubTariff.TRANSMISSION_NET_TARIFF);
|
||||||
|
|
||||||
private static final Map<String, PriceElement> NAME_MAP = Stream.of(values())
|
private static final Map<String, PriceComponent> NAME_MAP = Stream.of(values())
|
||||||
.collect(Collectors.toMap(PriceElement::toString, Function.identity()));
|
.collect(Collectors.toMap(PriceComponent::toString, Function.identity()));
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private @Nullable DatahubTariff datahubTariff;
|
private @Nullable DatahubTariff datahubTariff;
|
||||||
|
|
||||||
private PriceElement(String name, @Nullable DatahubTariff datahubTariff) {
|
private PriceComponent(String name, @Nullable DatahubTariff datahubTariff) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.datahubTariff = datahubTariff;
|
this.datahubTariff = datahubTariff;
|
||||||
}
|
}
|
||||||
@ -85,8 +85,8 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PriceElement fromString(final String name) {
|
public static PriceComponent fromString(final String name) {
|
||||||
PriceElement myEnum = NAME_MAP.get(name.toLowerCase());
|
PriceComponent myEnum = NAME_MAP.get(name.toLowerCase());
|
||||||
if (null == myEnum) {
|
if (null == myEnum) {
|
||||||
throw new IllegalArgumentException(String.format("'%s' has no corresponding value. Accepted values: %s",
|
throw new IllegalArgumentException(String.format("'%s' has no corresponding value. Accepted values: %s",
|
||||||
name, Arrays.asList(values())));
|
name, Arrays.asList(values())));
|
||||||
@ -109,30 +109,30 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
|
|
||||||
boolean isReducedElectricityTax = handler.isReducedElectricityTax();
|
boolean isReducedElectricityTax = handler.isReducedElectricityTax();
|
||||||
|
|
||||||
return getPrices(Arrays.stream(PriceElement.values())
|
return getPrices(Arrays.stream(PriceComponent.values())
|
||||||
.filter(element -> element != (isReducedElectricityTax ? PriceElement.ELECTRICITY_TAX
|
.filter(component -> component != (isReducedElectricityTax ? PriceComponent.ELECTRICITY_TAX
|
||||||
: PriceElement.REDUCED_ELECTRICITY_TAX))
|
: PriceComponent.REDUCED_ELECTRICITY_TAX))
|
||||||
.collect(Collectors.toSet()));
|
.collect(Collectors.toSet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RuleAction(label = "@text/action.get-prices.label", description = "@text/action.get-prices.description")
|
@RuleAction(label = "@text/action.get-prices.label", description = "@text/action.get-prices.description")
|
||||||
public @ActionOutput(name = "prices", type = "java.util.Map<java.time.Instant, java.math.BigDecimal>") Map<Instant, BigDecimal> getPrices(
|
public @ActionOutput(name = "prices", type = "java.util.Map<java.time.Instant, java.math.BigDecimal>") Map<Instant, BigDecimal> getPrices(
|
||||||
@ActionInput(name = "priceElements", label = "@text/action.get-prices.priceElements.label", description = "@text/action.get-prices.priceElements.description") @Nullable String priceElements) {
|
@ActionInput(name = "priceComponents", label = "@text/action.get-prices.priceComponents.label", description = "@text/action.get-prices.priceComponents.description") @Nullable String priceComponents) {
|
||||||
if (priceElements == null) {
|
if (priceComponents == null) {
|
||||||
logger.warn("Argument 'priceElements' is null");
|
logger.warn("Argument 'priceComponents' is null");
|
||||||
return Map.of();
|
return Map.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<PriceElement> priceElementsSet;
|
Set<PriceComponent> priceComponentsSet;
|
||||||
try {
|
try {
|
||||||
priceElementsSet = new HashSet<PriceElement>(
|
priceComponentsSet = new HashSet<PriceComponent>(
|
||||||
Arrays.stream(priceElements.split(",")).map(PriceElement::fromString).toList());
|
Arrays.stream(priceComponents.split(",")).map(PriceComponent::fromString).toList());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
logger.warn("{}", e.getMessage());
|
logger.warn("{}", e.getMessage());
|
||||||
return Map.of();
|
return Map.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
return getPrices(priceElementsSet);
|
return getPrices(priceComponentsSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RuleAction(label = "@text/action.calculate-price.label", description = "@text/action.calculate-price.description")
|
@RuleAction(label = "@text/action.calculate-price.label", description = "@text/action.calculate-price.description")
|
||||||
@ -233,7 +233,7 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Instant, BigDecimal> getPrices(Set<PriceElement> priceElements) {
|
private Map<Instant, BigDecimal> getPrices(Set<PriceComponent> priceComponents) {
|
||||||
EnergiDataServiceHandler handler = this.handler;
|
EnergiDataServiceHandler handler = this.handler;
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
logger.warn("EnergiDataServiceActions ThingHandler is null.");
|
logger.warn("EnergiDataServiceActions ThingHandler is null.");
|
||||||
@ -242,8 +242,8 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
|
|
||||||
Map<Instant, BigDecimal> prices;
|
Map<Instant, BigDecimal> prices;
|
||||||
boolean spotPricesRequired;
|
boolean spotPricesRequired;
|
||||||
if (priceElements.contains(PriceElement.SPOT_PRICE)) {
|
if (priceComponents.contains(PriceComponent.SPOT_PRICE)) {
|
||||||
if (priceElements.size() > 1 && !handler.getCurrency().equals(CURRENCY_DKK)) {
|
if (priceComponents.size() > 1 && !handler.getCurrency().equals(CURRENCY_DKK)) {
|
||||||
logger.warn("Cannot calculate sum when spot price currency is {}", handler.getCurrency());
|
logger.warn("Cannot calculate sum when spot price currency is {}", handler.getCurrency());
|
||||||
return Map.of();
|
return Map.of();
|
||||||
}
|
}
|
||||||
@ -254,13 +254,13 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
prices = new HashMap<>();
|
prices = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PriceElement priceElement : PriceElement.values()) {
|
for (PriceComponent priceComponent : PriceComponent.values()) {
|
||||||
DatahubTariff datahubTariff = priceElement.getDatahubTariff();
|
DatahubTariff datahubTariff = priceComponent.getDatahubTariff();
|
||||||
if (datahubTariff == null) {
|
if (datahubTariff == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priceElements.contains(priceElement)) {
|
if (priceComponents.contains(priceComponent)) {
|
||||||
Map<Instant, BigDecimal> tariffMap = handler.getTariffs(datahubTariff);
|
Map<Instant, BigDecimal> tariffMap = handler.getTariffs(datahubTariff);
|
||||||
mergeMaps(prices, tariffMap, !spotPricesRequired);
|
mergeMaps(prices, tariffMap, !spotPricesRequired);
|
||||||
}
|
}
|
||||||
@ -287,13 +287,13 @@ public class EnergiDataServiceActions implements ThingActions {
|
|||||||
* Static get prices method for DSL rule compatibility.
|
* Static get prices method for DSL rule compatibility.
|
||||||
*
|
*
|
||||||
* @param actions
|
* @param actions
|
||||||
* @param priceElements Comma-separated list of price elements to include in prices.
|
* @param priceComponents Comma-separated list of price components to include in prices.
|
||||||
* @return Map of prices
|
* @return Map of prices
|
||||||
*/
|
*/
|
||||||
public static Map<Instant, BigDecimal> getPrices(@Nullable ThingActions actions, @Nullable String priceElements) {
|
public static Map<Instant, BigDecimal> getPrices(@Nullable ThingActions actions, @Nullable String priceComponents) {
|
||||||
if (actions instanceof EnergiDataServiceActions serviceActions) {
|
if (actions instanceof EnergiDataServiceActions serviceActions) {
|
||||||
if (priceElements != null && !priceElements.isBlank()) {
|
if (priceComponents != null && !priceComponents.isBlank()) {
|
||||||
return serviceActions.getPrices(priceElements);
|
return serviceActions.getPrices(priceComponents);
|
||||||
} else {
|
} else {
|
||||||
return serviceActions.getPrices();
|
return serviceActions.getPrices();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,5 +108,5 @@ action.calculate-price.label = calculate price
|
|||||||
action.calculate-price.description = calculate price for power consumption in period excl. VAT
|
action.calculate-price.description = calculate price for power consumption in period excl. VAT
|
||||||
action.get-prices.label = get prices
|
action.get-prices.label = get prices
|
||||||
action.get-prices.description = get hourly prices excl. VAT
|
action.get-prices.description = get hourly prices excl. VAT
|
||||||
action.get-prices.priceElements.label = price elements
|
action.get-prices.priceComponents.label = price components
|
||||||
action.get-prices.priceElements.description = comma-separated list of price elements to include in sums
|
action.get-prices.priceComponents.description = comma-separated list of price components to include in sums
|
||||||
|
|||||||
@ -198,7 +198,7 @@ public class EnergiDataServiceActionsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getPricesTotalAllElements() throws IOException {
|
void getPricesTotalAllComponents() throws IOException {
|
||||||
mockCommonDatasets(actions);
|
mockCommonDatasets(actions);
|
||||||
|
|
||||||
Map<Instant, BigDecimal> actual = actions
|
Map<Instant, BigDecimal> actual = actions
|
||||||
@ -210,7 +210,7 @@ public class EnergiDataServiceActionsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getPricesInvalidPriceElement() throws IOException {
|
void getPricesInvalidPriceComponent() throws IOException {
|
||||||
mockCommonDatasets(actions);
|
mockCommonDatasets(actions);
|
||||||
|
|
||||||
Map<Instant, BigDecimal> actual = actions.getPrices("spotprice,nettarif");
|
Map<Instant, BigDecimal> actual = actions.getPrices("spotprice,nettarif");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user