[astro] Add option to force event to occur (#14132)
* fix issue 11424 Signed-off-by: lsiepel <leosiepel@gmail.com>
This commit is contained in:
parent
9001ee7426
commit
15a25db130
|
@ -130,6 +130,12 @@ OR
|
|||
|
||||
sunset is 22:10 but `latest` is set to 20:00 so the event/datetime value is moved 20:00.
|
||||
|
||||
**Force event:** For each trigger channel and `start`, `end` datetime value, you can force the `earliest`, `latest` time of the day, when the event is actually not taking place (e.g. astronomic dawn during summer in Sweden)
|
||||
e.g `sun#astroDawn earliest=6:00, latest=20:00 forceEvent=true`
|
||||
|
||||
astronomic dawn start is null but `earliest` is set to 06:00 so the event/datetime value is set to 06:00.
|
||||
|
||||
|
||||
## Full Example
|
||||
|
||||
Things:
|
||||
|
|
|
@ -25,4 +25,5 @@ public class AstroChannelConfig {
|
|||
public int offset = 0;
|
||||
public @Nullable String earliest;
|
||||
public @Nullable String latest;
|
||||
public boolean forceEvent = false;
|
||||
}
|
||||
|
|
|
@ -114,25 +114,44 @@ public interface Job extends SchedulerRunnable, Runnable {
|
|||
* @param channelId the channel ID
|
||||
*/
|
||||
public static void scheduleRange(String thingUID, AstroThingHandler astroHandler, Range range, String channelId) {
|
||||
Calendar start = range.getStart();
|
||||
Calendar end = range.getEnd();
|
||||
|
||||
// depending on the location you might not have a valid range for day/night, so skip the events:
|
||||
if (start == null || end == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Channel channel = astroHandler.getThing().getChannel(channelId);
|
||||
if (channel == null) {
|
||||
LOGGER.warn("Cannot find channel '{}' for thing '{}'.", channelId, astroHandler.getThing().getUID());
|
||||
return;
|
||||
}
|
||||
AstroChannelConfig config = channel.getConfiguration().as(AstroChannelConfig.class);
|
||||
Calendar configStart = truncateToSecond(applyConfig(start, config));
|
||||
Calendar configEnd = truncateToSecond(applyConfig(end, config));
|
||||
Range adjustedRange = adjustRangeToConfig(range, config);
|
||||
|
||||
scheduleEvent(thingUID, astroHandler, configStart, EVENT_START, channelId, true);
|
||||
scheduleEvent(thingUID, astroHandler, configEnd, EVENT_END, channelId, true);
|
||||
Calendar start = adjustedRange.getStart();
|
||||
Calendar end = adjustedRange.getEnd();
|
||||
|
||||
if (start == null || end == null) {
|
||||
LOGGER.debug("event was not scheduled as either start or end was null");
|
||||
return;
|
||||
}
|
||||
|
||||
scheduleEvent(thingUID, astroHandler, start, EVENT_START, channelId, true);
|
||||
scheduleEvent(thingUID, astroHandler, end, EVENT_END, channelId, true);
|
||||
}
|
||||
|
||||
public static Range adjustRangeToConfig(Range range, AstroChannelConfig config) {
|
||||
Calendar start = range.getStart();
|
||||
Calendar end = range.getEnd();
|
||||
|
||||
if (config.forceEvent && start == null) {
|
||||
start = getAdjustedEarliest(Calendar.getInstance(), config);
|
||||
}
|
||||
if (config.forceEvent && end == null) {
|
||||
end = getAdjustedLatest(Calendar.getInstance(), config);
|
||||
}
|
||||
|
||||
// depending on the location and configuration you might not have a valid range for day/night, so skip the
|
||||
// events:
|
||||
if (start == null || end == null) {
|
||||
return range;
|
||||
}
|
||||
|
||||
return new Range(truncateToSecond(applyConfig(start, config)), truncateToSecond(applyConfig(end, config)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -211,6 +211,14 @@ public class DateTimeUtils {
|
|||
return truncCal1.getTimeInMillis() >= truncCal2.getTimeInMillis();
|
||||
}
|
||||
|
||||
public static Calendar getAdjustedEarliest(Calendar cal, AstroChannelConfig config) {
|
||||
return adjustTime(cal, getMinutesFromTime(config.earliest));
|
||||
}
|
||||
|
||||
public static Calendar getAdjustedLatest(Calendar cal, AstroChannelConfig config) {
|
||||
return adjustTime(cal, getMinutesFromTime(config.latest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the config to the given calendar.
|
||||
*/
|
||||
|
@ -223,11 +231,11 @@ public class DateTimeUtils {
|
|||
cCal = cOffset;
|
||||
}
|
||||
|
||||
Calendar cEarliest = adjustTime(cCal, getMinutesFromTime(config.earliest));
|
||||
Calendar cEarliest = getAdjustedEarliest(cCal, config);
|
||||
if (cCal.before(cEarliest)) {
|
||||
return cEarliest;
|
||||
}
|
||||
Calendar cLatest = adjustTime(cCal, getMinutesFromTime(config.latest));
|
||||
Calendar cLatest = getAdjustedLatest(cCal, config);
|
||||
if (cCal.after(cLatest)) {
|
||||
return cLatest;
|
||||
}
|
||||
|
@ -244,6 +252,10 @@ public class DateTimeUtils {
|
|||
return cal;
|
||||
}
|
||||
|
||||
public static Calendar createCalendarForToday(int hour, int minute) {
|
||||
return DateTimeUtils.adjustTime(Calendar.getInstance(), hour * 60 + minute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a HH:MM string and returns the minutes.
|
||||
*/
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
<description>The latest time of the day for the event or the datetime value (hh:mm).</description>
|
||||
<context>time</context>
|
||||
</parameter>
|
||||
<parameter name="forceEvent" type="boolean">
|
||||
<label>Force Event</label>
|
||||
<description>Force event to occur according to Earliest/Latest, even when the event doesn't exist (null)</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
||||
|
|
|
@ -217,6 +217,8 @@ channel-type.astro.winter.state.pattern = %1$tF %1$tR
|
|||
|
||||
channel-type.config.astro.config.earliest.label = Earliest
|
||||
channel-type.config.astro.config.earliest.description = The earliest time of the day for the event or the datetime value (hh:mm).
|
||||
channel-type.config.astro.config.forceEvent.label = Force Event
|
||||
channel-type.config.astro.config.forceEvent.description = Force event to occur according to Earliest/Latest, even when the event doesn't exist (null)
|
||||
channel-type.config.astro.config.latest.label = Latest
|
||||
channel-type.config.astro.config.latest.description = The latest time of the day for the event or the datetime value (hh:mm).
|
||||
channel-type.config.astro.config.offset.label = Offset
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.astro.internal.job;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.astro.internal.config.AstroChannelConfig;
|
||||
import org.openhab.binding.astro.internal.model.Range;
|
||||
import org.openhab.binding.astro.internal.util.DateTimeUtils;
|
||||
|
||||
/**
|
||||
* Test class for {@link Job}.
|
||||
*
|
||||
* @author Leo Siepel - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class JobTest {
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adjustRangeToConfigForceTest() {
|
||||
// arrange
|
||||
AstroChannelConfig config = new AstroChannelConfig();
|
||||
config.earliest = "08:00";
|
||||
config.latest = "22:00";
|
||||
config.forceEvent = true;
|
||||
Calendar pointInTime = DateTimeUtils.createCalendarForToday(12, 0);
|
||||
Range startNull = new Range(null, pointInTime);
|
||||
Range endNull = new Range(pointInTime, null);
|
||||
Range bothNull = new Range(null, null);
|
||||
Range bothNNShouldCorrect = new Range(DateTimeUtils.createCalendarForToday(6, 0),
|
||||
DateTimeUtils.createCalendarForToday(22, 0));
|
||||
Range bothNNShouldNotCorrect = new Range(pointInTime, pointInTime);
|
||||
|
||||
// act
|
||||
Range startNullResult = Job.adjustRangeToConfig(startNull, config);
|
||||
Range endNullResult = Job.adjustRangeToConfig(endNull, config);
|
||||
Range bothNullResult = Job.adjustRangeToConfig(bothNull, config);
|
||||
Range bothNNShouldCorrectResult = Job.adjustRangeToConfig(bothNNShouldCorrect, config);
|
||||
Range bothNNSouldNotCorrectResult = Job.adjustRangeToConfig(bothNNShouldNotCorrect, config);
|
||||
|
||||
Calendar fixedStart = DateTimeUtils.getAdjustedEarliest(pointInTime, config);
|
||||
Calendar fixdedEnd = DateTimeUtils.getAdjustedLatest(pointInTime, config);
|
||||
|
||||
// assert
|
||||
assertEquals(fixedStart.getTime(), startNullResult.getStart().getTime());
|
||||
assertEquals(pointInTime.getTime(), startNullResult.getEnd().getTime());
|
||||
assertEquals(pointInTime, endNullResult.getStart());
|
||||
assertEquals(fixdedEnd, endNullResult.getEnd());
|
||||
assertEquals(fixedStart, bothNullResult.getStart());
|
||||
assertEquals(fixdedEnd, bothNullResult.getEnd());
|
||||
assertEquals(fixedStart, bothNNShouldCorrectResult.getStart());
|
||||
assertEquals(fixdedEnd, bothNNShouldCorrectResult.getEnd());
|
||||
assertEquals(pointInTime, bothNNSouldNotCorrectResult.getStart());
|
||||
assertEquals(pointInTime, bothNNSouldNotCorrectResult.getEnd());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adjustRangeToConfigTestSkipForceTest() {
|
||||
// arrange
|
||||
AstroChannelConfig config = new AstroChannelConfig();
|
||||
config.earliest = "08:00";
|
||||
config.latest = "22:00";
|
||||
config.forceEvent = false;
|
||||
Calendar pointInTime = DateTimeUtils.createCalendarForToday(12, 0);
|
||||
Range startNull = new Range(null, pointInTime);
|
||||
Range endNull = new Range(pointInTime, null);
|
||||
Range bothNull = new Range(null, null);
|
||||
Range bothNNShouldCorrect = new Range(DateTimeUtils.createCalendarForToday(6, 0),
|
||||
DateTimeUtils.createCalendarForToday(22, 0));
|
||||
Range bothNNShouldNotCorrect = new Range(pointInTime, pointInTime);
|
||||
|
||||
// act
|
||||
Range startNullResult = Job.adjustRangeToConfig(startNull, config);
|
||||
Range endNullResult = Job.adjustRangeToConfig(endNull, config);
|
||||
Range bothNullResult = Job.adjustRangeToConfig(bothNull, config);
|
||||
Range bothNNShouldCorrectResult = Job.adjustRangeToConfig(bothNNShouldCorrect, config);
|
||||
Range bothNNSouldNotCorrectResult = Job.adjustRangeToConfig(bothNNShouldNotCorrect, config);
|
||||
|
||||
Calendar fixedStart = DateTimeUtils.getAdjustedEarliest(pointInTime, config);
|
||||
Calendar fixdedEnd = DateTimeUtils.getAdjustedLatest(pointInTime, config);
|
||||
|
||||
// assert
|
||||
assertEquals(null, startNullResult.getStart());
|
||||
assertEquals(pointInTime, startNullResult.getEnd());
|
||||
assertEquals(pointInTime, endNullResult.getStart());
|
||||
assertEquals(null, endNullResult.getEnd());
|
||||
assertEquals(null, bothNullResult.getStart());
|
||||
assertEquals(null, bothNullResult.getEnd());
|
||||
assertEquals(fixedStart, bothNNShouldCorrectResult.getStart());
|
||||
assertEquals(fixdedEnd, bothNNShouldCorrectResult.getEnd());
|
||||
assertEquals(pointInTime, bothNNSouldNotCorrectResult.getStart());
|
||||
assertEquals(pointInTime, bothNNSouldNotCorrectResult.getEnd());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue