]> git.basschouten.com Git - openhab-addons.git/commitdiff
[astro] Add option to force event to occur (#14132)
authorlsiepel <leosiepel@gmail.com>
Sun, 29 Jan 2023 21:15:38 +0000 (22:15 +0100)
committerGitHub <noreply@github.com>
Sun, 29 Jan 2023 21:15:38 +0000 (22:15 +0100)
* fix issue 11424

Signed-off-by: lsiepel <leosiepel@gmail.com>
bundles/org.openhab.binding.astro/README.md
bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/config/AstroChannelConfig.java
bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/Job.java
bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/util/DateTimeUtils.java
bundles/org.openhab.binding.astro/src/main/resources/OH-INF/config/config.xml
bundles/org.openhab.binding.astro/src/main/resources/OH-INF/i18n/astro.properties
bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/job/JobTest.java [new file with mode: 0644]

index 0ba39332f63acaf79300685d9db4cee9d692a33e..3f9de1e514dcda43e1f0b2a13bda958c7e5bfff6 100644 (file)
@@ -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:
index e308aa525cbfe9eb7470396108579f1e8557a425..c07dac61581eb4fad05d45cb6f7ec7d9c4022973 100644 (file)
@@ -25,4 +25,5 @@ public class AstroChannelConfig {
     public int offset = 0;
     public @Nullable String earliest;
     public @Nullable String latest;
+    public boolean forceEvent = false;
 }
index 530280fcd15c9eea0d4d411b0ba315c390d514fa..29f7772bce8ac03fe640b19f286dda2d7fb81af8 100644 (file)
@@ -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);
+
+        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;
+        }
 
-        scheduleEvent(thingUID, astroHandler, configStart, EVENT_START, channelId, true);
-        scheduleEvent(thingUID, astroHandler, configEnd, EVENT_END, channelId, true);
+        return new Range(truncateToSecond(applyConfig(start, config)), truncateToSecond(applyConfig(end, config)));
     }
 
     /**
index 05eb5bffea20772c6721e714895d9c5f5b326482..1718d34e533c7a65a8edc4bc286d846895e6bf24 100644 (file)
@@ -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.
      */
index 40f87cd121d148981d6705a41f19c664af346d4f..d5fd63cff9db2701b2804cd3a5ba231a7546c433 100644 (file)
                        <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>
index bb619a600bd0e0338bf5335ea762cbdb583cee32..e61681d9bcb413db460c589be4b25d9891c98a0f 100644 (file)
@@ -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
diff --git a/bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/job/JobTest.java b/bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/job/JobTest.java
new file mode 100644 (file)
index 0000000..9949ce1
--- /dev/null
@@ -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());
+    }
+}