mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[aWATTar] push test coverage and improve code readability
Signed-off-by: Thomas Leber <thomas@tl-photography.at>
This commit is contained in:
parent
2cd8902017
commit
71b17c018e
@ -12,6 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.awattar.internal;
|
package org.openhab.binding.awattar.internal;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +49,18 @@ public abstract class AwattarBestPriceResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isActive();
|
/**
|
||||||
|
* Returns true if the best price is active.
|
||||||
|
*
|
||||||
|
* @param now the current time
|
||||||
|
* @return true if the best price is active, false otherwise
|
||||||
|
*/
|
||||||
|
public abstract boolean isActive(Instant now);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hours of the best price.
|
||||||
|
*
|
||||||
|
* @return the hours of the best price as a string
|
||||||
|
*/
|
||||||
public abstract String getHours();
|
public abstract String getHours();
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,8 @@ public class AwattarConsecutiveBestPriceResult extends AwattarBestPriceResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive() {
|
public boolean isActive(Instant now) {
|
||||||
return contains(Instant.now().toEpochMilli());
|
return contains(now.toEpochMilli());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(long timestamp) {
|
public boolean contains(long timestamp) {
|
||||||
|
@ -64,8 +64,8 @@ public class AwattarNonConsecutiveBestPriceResult extends AwattarBestPriceResult
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive() {
|
public boolean isActive(Instant now) {
|
||||||
return members.stream().anyMatch(x -> x.timerange().contains(Instant.now().toEpochMilli()));
|
return members.stream().anyMatch(x -> x.timerange().contains(now.toEpochMilli()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -73,16 +73,9 @@ public class AwattarNonConsecutiveBestPriceResult extends AwattarBestPriceResult
|
|||||||
return String.format("NonConsecutiveBestpriceResult with %s", members.toString());
|
return String.format("NonConsecutiveBestpriceResult with %s", members.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sort() {
|
|
||||||
if (!sorted) {
|
|
||||||
members.sort(Comparator.comparingLong(p -> p.timerange().start()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHours() {
|
public String getHours() {
|
||||||
boolean second = false;
|
boolean second = false;
|
||||||
sort();
|
|
||||||
StringBuilder res = new StringBuilder();
|
StringBuilder res = new StringBuilder();
|
||||||
|
|
||||||
for (AwattarPrice price : members) {
|
for (AwattarPrice price : members) {
|
||||||
|
@ -23,7 +23,6 @@ import static org.openhab.binding.awattar.internal.AwattarUtil.getCalendarForHou
|
|||||||
import static org.openhab.binding.awattar.internal.AwattarUtil.getDuration;
|
import static org.openhab.binding.awattar.internal.AwattarUtil.getDuration;
|
||||||
import static org.openhab.binding.awattar.internal.AwattarUtil.getMillisToNextMinute;
|
import static org.openhab.binding.awattar.internal.AwattarUtil.getMillisToNextMinute;
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -163,7 +162,7 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
|
|||||||
long diff;
|
long diff;
|
||||||
switch (channelId) {
|
switch (channelId) {
|
||||||
case CHANNEL_ACTIVE:
|
case CHANNEL_ACTIVE:
|
||||||
state = OnOffType.from(result.isActive());
|
state = OnOffType.from(result.isActive(getNow(zoneId).toInstant()));
|
||||||
break;
|
break;
|
||||||
case CHANNEL_START:
|
case CHANNEL_START:
|
||||||
state = new DateTimeType(Instant.ofEpochMilli(result.getStart()));
|
state = new DateTimeType(Instant.ofEpochMilli(result.getStart()));
|
||||||
@ -172,7 +171,7 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
|
|||||||
state = new DateTimeType(Instant.ofEpochMilli(result.getEnd()));
|
state = new DateTimeType(Instant.ofEpochMilli(result.getEnd()));
|
||||||
break;
|
break;
|
||||||
case CHANNEL_COUNTDOWN:
|
case CHANNEL_COUNTDOWN:
|
||||||
diff = result.getStart() - Instant.now().toEpochMilli();
|
diff = result.getStart() - getNow(zoneId).toInstant().toEpochMilli();
|
||||||
if (diff >= 0) {
|
if (diff >= 0) {
|
||||||
state = getDuration(diff);
|
state = getDuration(diff);
|
||||||
} else {
|
} else {
|
||||||
@ -180,8 +179,8 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CHANNEL_REMAINING:
|
case CHANNEL_REMAINING:
|
||||||
if (result.isActive()) {
|
if (result.isActive(getNow(zoneId).toInstant())) {
|
||||||
diff = result.getEnd() - Instant.now().toEpochMilli();
|
diff = result.getEnd() - getNow(zoneId).toInstant().toEpochMilli();
|
||||||
state = getDuration(diff);
|
state = getDuration(diff);
|
||||||
} else {
|
} else {
|
||||||
state = QuantityType.valueOf(0, Units.MINUTE);
|
state = QuantityType.valueOf(0, Units.MINUTE);
|
||||||
@ -216,20 +215,49 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time range for the given start hour and duration.
|
||||||
|
*
|
||||||
|
* @param start the start hour (0-23)
|
||||||
|
* @param duration the duration in hours
|
||||||
|
* @param zoneId the time zone to use
|
||||||
|
* @return the range
|
||||||
|
*/
|
||||||
protected TimeRange getRange(int start, int duration, ZoneId zoneId) {
|
protected TimeRange getRange(int start, int duration, ZoneId zoneId) {
|
||||||
ZonedDateTime startCal = getCalendarForHour(start, zoneId);
|
ZonedDateTime startTime = getStarTime(start, zoneId);
|
||||||
ZonedDateTime endCal = startCal.plusHours(duration);
|
ZonedDateTime endTime = startTime.plusHours(duration);
|
||||||
ZonedDateTime now = ZonedDateTime.now(zoneId);
|
ZonedDateTime now = getNow(zoneId);
|
||||||
if (now.getHour() < start) {
|
if (now.getHour() < start) {
|
||||||
// we are before the range, so we might be still within the last range
|
// we are before the range, so we might be still within the last range
|
||||||
startCal = startCal.minusDays(1);
|
startTime = startTime.minusDays(1);
|
||||||
endCal = endCal.minusDays(1);
|
endTime = endTime.minusDays(1);
|
||||||
}
|
}
|
||||||
if (endCal.toInstant().toEpochMilli() < Instant.now().toEpochMilli()) {
|
if (endTime.toInstant().toEpochMilli() < now.toInstant().toEpochMilli()) {
|
||||||
// span is in the past, add one day
|
// span is in the past, add one day
|
||||||
startCal = startCal.plusDays(1);
|
startTime = startTime.plusDays(1);
|
||||||
endCal = endCal.plusDays(1);
|
endTime = endTime.plusDays(1);
|
||||||
}
|
}
|
||||||
return new TimeRange(startCal.toInstant().toEpochMilli(), endCal.toInstant().toEpochMilli());
|
return new TimeRange(startTime.toInstant().toEpochMilli(), endTime.toInstant().toEpochMilli());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the start time for the given hour.
|
||||||
|
*
|
||||||
|
* @param start the hour. Must be between 0 and 23.
|
||||||
|
* @param zoneId the time zone
|
||||||
|
* @return the start time
|
||||||
|
*/
|
||||||
|
protected ZonedDateTime getStarTime(int start, ZoneId zoneId) {
|
||||||
|
return getCalendarForHour(start, zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current time.
|
||||||
|
*
|
||||||
|
* @param zoneId the time zone
|
||||||
|
* @return the current time
|
||||||
|
*/
|
||||||
|
protected ZonedDateTime getNow(ZoneId zoneId) {
|
||||||
|
return ZonedDateTime.now(zoneId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,18 @@ import static org.hamcrest.Matchers.nullValue;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_ACTIVE;
|
||||||
|
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_COUNTDOWN;
|
||||||
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_END;
|
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_END;
|
||||||
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_HOURS;
|
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_HOURS;
|
||||||
|
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_REMAINING;
|
||||||
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_START;
|
import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_START;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -58,6 +62,8 @@ import org.openhab.binding.awattar.internal.dto.AwattarApiData;
|
|||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.i18n.TimeZoneProvider;
|
import org.openhab.core.i18n.TimeZoneProvider;
|
||||||
import org.openhab.core.library.types.DateTimeType;
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.QuantityType;
|
||||||
import org.openhab.core.library.types.StringType;
|
import org.openhab.core.library.types.StringType;
|
||||||
import org.openhab.core.test.java.JavaTest;
|
import org.openhab.core.test.java.JavaTest;
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
@ -166,31 +172,98 @@ public class AwattarBridgeHandlerTest extends JavaTest {
|
|||||||
|
|
||||||
public static Stream<Arguments> testBestpriceHandler() {
|
public static Stream<Arguments> testBestpriceHandler() {
|
||||||
return Stream.of( //
|
return Stream.of( //
|
||||||
Arguments.of(1, true, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
|
Arguments.of(24, 1, true, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
|
||||||
Arguments.of(1, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
Arguments.of(24, 1, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
||||||
Arguments.of(1, true, CHANNEL_HOURS, new StringType("14")),
|
Arguments.of(24, 1, true, CHANNEL_HOURS, new StringType("14")),
|
||||||
Arguments.of(1, false, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
|
Arguments.of(24, 1, false, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
|
||||||
Arguments.of(1, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
Arguments.of(24, 1, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
||||||
Arguments.of(1, false, CHANNEL_HOURS, new StringType("14")),
|
Arguments.of(24, 1, false, CHANNEL_HOURS, new StringType("14")),
|
||||||
Arguments.of(2, true, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
|
Arguments.of(24, 2, true, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
|
||||||
Arguments.of(2, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
Arguments.of(24, 2, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
||||||
Arguments.of(2, true, CHANNEL_HOURS, new StringType("13,14")),
|
Arguments.of(24, 2, true, CHANNEL_HOURS, new StringType("13,14")),
|
||||||
Arguments.of(2, false, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
|
Arguments.of(24, 2, false, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
|
||||||
Arguments.of(2, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
Arguments.of(24, 2, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
|
||||||
Arguments.of(2, false, CHANNEL_HOURS, new StringType("13,14")));
|
Arguments.of(24, 2, false, CHANNEL_HOURS, new StringType("13,14")),
|
||||||
|
Arguments.of(34, 4, false, CHANNEL_START, new DateTimeType("2024-06-15T12:00:00.000+0200")),
|
||||||
|
Arguments.of(34, 4, false, CHANNEL_END, new DateTimeType("2024-06-15T16:00:00.000+0200")),
|
||||||
|
Arguments.of(34, 4, false, CHANNEL_HOURS, new StringType("12,13,14,15")),
|
||||||
|
Arguments.of(34, 8, false, CHANNEL_START, new DateTimeType("2024-06-15T12:00:00.000+0200")),
|
||||||
|
Arguments.of(34, 8, false, CHANNEL_END, new DateTimeType("2024-06-16T16:00:00.000+0200")),
|
||||||
|
Arguments.of(34, 8, false, CHANNEL_HOURS, new StringType("12,13,14,15,16,13,14,15")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource
|
@MethodSource
|
||||||
void testBestpriceHandler(int length, boolean consecutive, String channelId, State expectedState) {
|
void testBestpriceHandler(int rangeDuration, int length, boolean consecutive, String channelId,
|
||||||
|
State expectedState) {
|
||||||
ThingUID bestPriceUid = new ThingUID(AwattarBindingConstants.THING_TYPE_BESTPRICE, "foo");
|
ThingUID bestPriceUid = new ThingUID(AwattarBindingConstants.THING_TYPE_BESTPRICE, "foo");
|
||||||
Map<String, Object> config = Map.of("length", length, "consecutive", consecutive);
|
Map<String, Object> config = Map.of("rangeDuration", rangeDuration, "length", length, "consecutive",
|
||||||
|
consecutive);
|
||||||
when(bestpriceMock.getConfiguration()).thenReturn(new Configuration(config));
|
when(bestpriceMock.getConfiguration()).thenReturn(new Configuration(config));
|
||||||
|
|
||||||
AwattarBestPriceHandler handler = new AwattarBestPriceHandler(bestpriceMock, timeZoneProviderMock) {
|
AwattarBestPriceHandler handler = new AwattarBestPriceHandler(bestpriceMock, timeZoneProviderMock) {
|
||||||
@Override
|
protected ZonedDateTime getStarTime(int start, ZoneId zoneId) {
|
||||||
protected TimeRange getRange(int start, int duration, ZoneId zoneId) {
|
return ZonedDateTime.of(2024, 6, 15, 12, 0, 0, 0, zoneId);
|
||||||
return new TimeRange(1718402400000L, 1718488800000L);
|
}
|
||||||
|
|
||||||
|
protected ZonedDateTime getNow(ZoneId zoneId) {
|
||||||
|
return ZonedDateTime.of(2024, 6, 15, 12, 0, 0, 0, zoneId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.setCallback(bestPriceCallbackMock);
|
||||||
|
|
||||||
|
ChannelUID channelUID = new ChannelUID(bestPriceUid, channelId);
|
||||||
|
handler.refreshChannel(channelUID);
|
||||||
|
verify(bestPriceCallbackMock).stateUpdated(channelUID, expectedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> testBestpriceHandler_channels() {
|
||||||
|
return Stream.of( //
|
||||||
|
Arguments.of(12, 0, 24, 1, true, CHANNEL_HOURS, new StringType("14")),
|
||||||
|
Arguments.of(12, 0, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(false)),
|
||||||
|
Arguments.of(12, 0, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("120 min")),
|
||||||
|
Arguments.of(12, 0, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")),
|
||||||
|
|
||||||
|
Arguments.of(13, 59, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("1 min")),
|
||||||
|
Arguments.of(13, 59, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")),
|
||||||
|
Arguments.of(13, 59, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(false)),
|
||||||
|
Arguments.of(13, 59, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(false)),
|
||||||
|
|
||||||
|
Arguments.of(14, 01, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("0 min")),
|
||||||
|
Arguments.of(14, 01, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("59 min")),
|
||||||
|
Arguments.of(14, 01, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(true)),
|
||||||
|
Arguments.of(14, 01, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(true)),
|
||||||
|
|
||||||
|
Arguments.of(14, 59, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("0 min")),
|
||||||
|
Arguments.of(14, 59, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("1 min")),
|
||||||
|
Arguments.of(14, 59, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(true)),
|
||||||
|
Arguments.of(14, 59, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(true)),
|
||||||
|
|
||||||
|
Arguments.of(15, 00, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("0 min")),
|
||||||
|
Arguments.of(15, 00, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")),
|
||||||
|
Arguments.of(15, 00, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(false)),
|
||||||
|
Arguments.of(15, 00, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(false)),
|
||||||
|
|
||||||
|
Arguments.of(12, 0, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
void testBestpriceHandler_channels(int currentHour, int currentMinute, int rangeDuration, int length,
|
||||||
|
boolean consecutive, String channelId, State expectedState) {
|
||||||
|
ThingUID bestPriceUid = new ThingUID(AwattarBindingConstants.THING_TYPE_BESTPRICE, "foo");
|
||||||
|
Map<String, Object> config = Map.of("rangeDuration", rangeDuration, "length", length, "consecutive",
|
||||||
|
consecutive);
|
||||||
|
when(bestpriceMock.getConfiguration()).thenReturn(new Configuration(config));
|
||||||
|
|
||||||
|
AwattarBestPriceHandler handler = new AwattarBestPriceHandler(bestpriceMock, timeZoneProviderMock) {
|
||||||
|
protected ZonedDateTime getStarTime(int start, ZoneId zoneId) {
|
||||||
|
return ZonedDateTime.of(2024, 6, 15, 0, 0, 0, 0, zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ZonedDateTime getNow(ZoneId zoneId) {
|
||||||
|
return ZonedDateTime.of(2024, 6, 15, currentHour, currentMinute, 0, 0, zoneId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user