2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.energidataservice.internal;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.equalTo;
17 import static org.hamcrest.Matchers.is;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.math.BigDecimal;
22 import java.nio.charset.StandardCharsets;
23 import java.time.Clock;
24 import java.time.Instant;
25 import java.time.LocalDateTime;
26 import java.time.temporal.ChronoUnit;
27 import java.util.Arrays;
29 import java.util.Objects;
31 import org.eclipse.jdt.annotation.NonNullByDefault;
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.api.extension.ExtendWith;
34 import org.mockito.junit.jupiter.MockitoExtension;
35 import org.openhab.binding.energidataservice.internal.api.dto.DatahubPricelistRecords;
36 import org.openhab.binding.energidataservice.internal.api.serialization.LocalDateTimeDeserializer;
38 import com.google.gson.Gson;
39 import com.google.gson.GsonBuilder;
42 * Tests for {@link PriceListParser}.
44 * @author Jacob Laursen - Initial contribution
47 @ExtendWith(MockitoExtension.class)
48 public class PriceListParserTest {
50 private Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer())
53 private <T> T getObjectFromJson(String filename, Class<T> clazz) throws IOException {
54 try (InputStream inputStream = PriceListParserTest.class.getResourceAsStream(filename)) {
55 if (inputStream == null) {
56 throw new IOException("Input stream is null");
58 byte[] bytes = inputStream.readAllBytes();
60 throw new IOException("Resulting byte-array empty");
62 String json = new String(bytes, StandardCharsets.UTF_8);
63 return Objects.requireNonNull(gson.fromJson(json, clazz));
68 void toHourlyNoChanges() throws IOException {
69 PriceListParser priceListParser = new PriceListParser(
70 Clock.fixed(Instant.parse("2023-01-23T12:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
71 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistN1.json", DatahubPricelistRecords.class);
72 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
74 assertThat(tariffMap.size(), is(60));
75 assertThat(tariffMap.get(Instant.parse("2023-01-23T15:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
76 assertThat(tariffMap.get(Instant.parse("2023-01-23T16:00:00Z")), is(equalTo(new BigDecimal("1.05619"))));
77 assertThat(tariffMap.get(Instant.parse("2023-01-24T15:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
78 assertThat(tariffMap.get(Instant.parse("2023-01-24T16:00:00Z")), is(equalTo(new BigDecimal("1.05619"))));
82 void toHourlyNewTariffTomorrowWhenSummertime() throws IOException {
83 PriceListParser priceListParser = new PriceListParser(
84 Clock.fixed(Instant.parse("2023-03-31T12:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
85 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistN1.json", DatahubPricelistRecords.class);
86 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
88 assertThat(tariffMap.size(), is(60));
89 assertThat(tariffMap.get(Instant.parse("2023-03-31T14:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
90 assertThat(tariffMap.get(Instant.parse("2023-03-31T15:00:00Z")), is(equalTo(new BigDecimal("1.05619"))));
91 assertThat(tariffMap.get(Instant.parse("2023-04-01T14:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
92 assertThat(tariffMap.get(Instant.parse("2023-04-01T15:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
96 void toHourlyNewTariffAtMidnight() throws IOException {
97 PriceListParser priceListParser = new PriceListParser(
98 Clock.fixed(Instant.parse("2022-12-31T12:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
99 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistN1.json", DatahubPricelistRecords.class);
100 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList(), "CD");
102 assertThat(tariffMap.size(), is(60));
103 assertThat(tariffMap.get(Instant.parse("2022-12-31T22:00:00Z")), is(equalTo(new BigDecimal("0.407717"))));
104 assertThat(tariffMap.get(Instant.parse("2022-12-31T23:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
105 assertThat(tariffMap.get(Instant.parse("2023-01-01T00:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
109 void toHourlyDiscount() throws IOException {
110 PriceListParser priceListParser = new PriceListParser(
111 Clock.fixed(Instant.parse("2022-12-31T12:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
112 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistN1.json", DatahubPricelistRecords.class);
113 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList(),
116 assertThat(tariffMap.size(), is(60));
117 assertThat(tariffMap.get(Instant.parse("2022-12-31T22:00:00Z")), is(equalTo(new BigDecimal("-0.407717"))));
118 assertThat(tariffMap.get(Instant.parse("2022-12-31T23:00:00Z")), is(equalTo(new BigDecimal("0.0"))));
119 assertThat(tariffMap.get(Instant.parse("2023-01-01T00:00:00Z")), is(equalTo(new BigDecimal("0.0"))));
123 void toHourlyTariffAndDiscountIsSum() throws IOException {
124 PriceListParser priceListParser = new PriceListParser(
125 Clock.fixed(Instant.parse("2022-11-30T15:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
126 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistN1.json", DatahubPricelistRecords.class);
127 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
129 assertThat(tariffMap.size(), is(57));
130 assertThat(tariffMap.get(Instant.parse("2022-11-30T15:00:00Z")), is(equalTo(new BigDecimal("0.387517"))));
131 assertThat(tariffMap.get(Instant.parse("2022-11-30T16:00:00Z")), is(equalTo(new BigDecimal("0.973404"))));
135 void toHourlyTariffAndDiscountIsFree() throws IOException {
136 PriceListParser priceListParser = new PriceListParser(
137 Clock.fixed(Instant.parse("2022-12-31T12:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
138 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistN1.json", DatahubPricelistRecords.class);
139 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
141 assertThat(tariffMap.size(), is(60));
142 assertThat(tariffMap.get(Instant.parse("2022-12-31T16:00:00Z")), is(equalTo(new BigDecimal("0.000000"))));
143 assertThat(tariffMap.get(Instant.parse("2022-12-31T22:00:00Z")), is(equalTo(new BigDecimal("0.000000"))));
144 assertThat(tariffMap.get(Instant.parse("2022-12-31T23:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
145 assertThat(tariffMap.get(Instant.parse("2023-01-01T00:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
149 void toHourlyFixedTariff() throws IOException {
150 PriceListParser priceListParser = new PriceListParser(
151 Clock.fixed(Instant.parse("2022-12-31T23:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
152 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistNordEnergi.json",
153 DatahubPricelistRecords.class);
154 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
156 assertThat(tariffMap.size(), is(25)); // No records in dataset before 2023-01-01
157 for (Instant i = Instant.parse("2022-12-31T23:00:00Z"); i
158 .isBefore(Instant.parse("2023-01-02T00:00:00Z")); i = i.plus(1, ChronoUnit.HOURS)) {
159 assertThat(tariffMap.get(i), is(equalTo(new BigDecimal("0.245"))));
164 void toHourlyDailyTariffs() throws IOException {
165 PriceListParser priceListParser = new PriceListParser(
166 Clock.fixed(Instant.parse("2023-01-28T04:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
167 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistTrefor.json",
168 DatahubPricelistRecords.class);
169 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
171 assertThat(tariffMap.size(), is(68));
172 assertThat(tariffMap.get(Instant.parse("2023-01-28T04:00:00Z")), is(equalTo(new BigDecimal("0.2581"))));
173 assertThat(tariffMap.get(Instant.parse("2023-01-28T05:00:00Z")), is(equalTo(new BigDecimal("0.7742"))));
174 assertThat(tariffMap.get(Instant.parse("2023-01-28T16:00:00Z")), is(equalTo(new BigDecimal("2.3227"))));
175 assertThat(tariffMap.get(Instant.parse("2023-01-28T20:00:00Z")), is(equalTo(new BigDecimal("0.7742"))));
176 assertThat(tariffMap.get(Instant.parse("2023-01-28T23:00:00Z")), is(equalTo(new BigDecimal("0.2581"))));
177 assertThat(tariffMap.get(Instant.parse("2023-01-29T05:00:00Z")), is(equalTo(new BigDecimal("0.7742"))));
178 assertThat(tariffMap.get(Instant.parse("2023-01-29T16:00:00Z")), is(equalTo(new BigDecimal("2.3227"))));
179 assertThat(tariffMap.get(Instant.parse("2023-01-29T20:00:00Z")), is(equalTo(new BigDecimal("0.7742"))));
183 void toHourlySystemTariff() throws IOException {
184 PriceListParser priceListParser = new PriceListParser(
185 Clock.fixed(Instant.parse("2023-06-30T21:00:00Z"), EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
186 DatahubPricelistRecords records = getObjectFromJson("DatahubPricelistElectricityTax.json",
187 DatahubPricelistRecords.class);
188 Map<Instant, BigDecimal> tariffMap = priceListParser.toHourly(Arrays.stream(records.records()).toList());
190 assertThat(tariffMap.size(), is(51));
191 assertThat(tariffMap.get(Instant.parse("2023-06-30T21:00:00Z")), is(equalTo(new BigDecimal("0.008"))));
192 assertThat(tariffMap.get(Instant.parse("2023-06-30T22:00:00Z")), is(equalTo(new BigDecimal("0.697"))));