diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleBuilder.java b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleBuilder.java index d0ddf316..f5b7f47b 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleBuilder.java +++ b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleBuilder.java @@ -29,6 +29,7 @@ import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedCommandExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedUpdateExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRulePreconditionContext; +import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleStartupExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimeTimerExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedCronExecutionContext; @@ -54,15 +55,16 @@ public class JRuleBuilder { private Duration timedLock = null; private Duration delayed = null; - final private List preConditions = new ArrayList<>(); + private final List preConditions = new ArrayList<>(); - final private List whenThingTriggers = new ArrayList<>(); - final private List whenChannelTriggers = new ArrayList<>(); - final private List whenItemReceivedCommandTriggers = new ArrayList<>(); - final private List whenItemChangedTriggers = new ArrayList<>(); - final private List whenItemReceivedUpdateTriggers = new ArrayList<>(); - final private List whenCronTriggers = new ArrayList<>(); - final private List whenTimeTriggers = new ArrayList<>(); + private final List whenStartupTriggers = new ArrayList<>(); + private final List whenThingTriggers = new ArrayList<>(); + private final List whenChannelTriggers = new ArrayList<>(); + private final List whenItemReceivedCommandTriggers = new ArrayList<>(); + private final List whenItemChangedTriggers = new ArrayList<>(); + private final List whenItemReceivedUpdateTriggers = new ArrayList<>(); + private final List whenCronTriggers = new ArrayList<>(); + private final List whenTimeTriggers = new ArrayList<>(); JRuleBuilder(JRuleEngine jRuleEngine, String ruleName, JRuleInvocationCallback invocationCallback) { this.jRuleEngine = jRuleEngine; @@ -105,6 +107,11 @@ public JRuleBuilder preCondition(String itemName, Condition condition) { return this; } + public JRuleBuilder whenStartupTrigger(int level) { + whenStartupTriggers.add(new WhenStartupTrigger(level)); + return this; + } + public JRuleBuilder whenThingTrigger(String thingName, @Nullable JRuleThingStatus from, @Nullable JRuleThingStatus to) { whenThingTriggers.add(new WhenThingTrigger(thingName, from, to)); @@ -165,6 +172,15 @@ public boolean build() { Optional.ofNullable(data.condition.neq))) .toList(); + whenStartupTriggers.forEach(data -> { + JRuleStartupExecutionContext context = new JRuleStartupExecutionContext(uid, logName, loggingTags, + invocationCallback, preconditionContexts, timedLock, delayed, data.level); + jRuleEngine.addToContext(context, enableRule); + jRuleEngine.ruleLoadingStatistics.addStartupTrigger(); + ruleModuleEntry.addJRuleWhenStartupTrigger(context); + addedToContext.set(true); + }); + whenThingTriggers.forEach(data -> { JRuleThingExecutionContext context = new JRuleThingExecutionContext(uid, logName, loggingTags, invocationCallback, Optional.ofNullable(data.thingName), Optional.ofNullable(data.from), @@ -261,6 +277,9 @@ private JRuleItemExecutionContext.JRuleConditionContext toJRuleConditionContext( private record PreCondition(String itemName, Condition condition) { } + private record WhenStartupTrigger(int level) { + } + private record WhenThingTrigger(String thingName, JRuleThingStatus from, JRuleThingStatus to) { } diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java index db72e86f..6fb84852 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java +++ b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java @@ -42,6 +42,7 @@ import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleChannelExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemExecutionContext; +import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleStartupExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedExecutionContext; import org.openhab.automation.jrule.internal.engine.timer.JRuleTimerExecutor; @@ -63,6 +64,7 @@ import org.openhab.automation.jrule.rules.JRuleWhenItemChange; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate; +import org.openhab.automation.jrule.rules.JRuleWhenStartup; import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger; import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger; import org.openhab.automation.jrule.rules.event.JRuleEvent; @@ -151,7 +153,7 @@ private void add(Method method, JRule jRule, boolean enableRule) { logWarn("Skipping non-public method {} on class {}", method.getName(), jRule.getClass().getName()); return; } - // Check if method is has none or a single parameter + // Check if method has none or a single parameter if (method.getParameterCount() > 1) { logWarn("Skipping method {} on class {}. Rule methods should have none or a single parameter", method.getName(), jRule.getClass().getName()); @@ -223,6 +225,8 @@ private void add(Method method, JRule jRule, boolean enableRule) { .orElse(null), Optional.of(jRuleWhen.from()).filter(s -> s != JRuleThingStatus.THING_UNKNOWN).orElse(null), Optional.of(jRuleWhen.to()).filter(s -> s != JRuleThingStatus.THING_UNKNOWN).orElse(null))); + Arrays.stream(method.getAnnotationsByType(JRuleWhenStartup.class)) + .forEach(jRuleWhen -> jRuleBuilder.whenStartupTrigger(jRuleWhen.level())); // Check if rule was actually activated, i.e. if triggers are present if (!jRuleBuilder.build()) { @@ -324,7 +328,8 @@ public boolean matchPrecondition(JRuleExecutionContext jRuleExecutionContext) { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_ITEM_EVENT) || evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_CHANNEL_EVENT) - || evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_THING_STATUS_EVENT)) { + || evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_THING_STATUS_EVENT) + || evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_STARTUP_EVENT)) { fire((AbstractEvent) evt.getNewValue()); } } @@ -365,6 +370,14 @@ public boolean watchingForItem(String itemName) { return b; } + public boolean watchingForStartlevel(Integer startlevel) { + boolean b = this.contextList.stream().filter(context -> context instanceof JRuleStartupExecutionContext) + .map(context -> ((JRuleStartupExecutionContext) context)) + .anyMatch(context -> context.getStartupLevel() == startlevel); + logDebug("watching for startup: '{}'? -> {}", startlevel, b); + return b; + } + public boolean watchingForChannel(String channel) { boolean b = this.contextList.stream().filter(context -> context instanceof JRuleChannelExecutionContext) .map(context -> ((JRuleChannelExecutionContext) context)) @@ -513,7 +526,7 @@ public JRuleBuilder createJRuleBuilder(String ruleName, JRule jRule, Method meth method.invoke(jRule); } } catch (InvocationTargetException e) { - logError("Error in rule: {}\ntarget: {}", ExceptionUtils.getStackTrace(e), + logError("Error in rule: {}k\ntarget: {}", ExceptionUtils.getStackTrace(e), ExceptionUtils.getStackTrace(e.getCause())); } catch (IllegalAccessException | IllegalArgumentException | SecurityException e) { logError("Error calling rule method '{}#{}': {}", method.getDeclaringClass().getName(), diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleLoadingStatistics.java b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleLoadingStatistics.java index 2897cfe4..6e5dd0f9 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleLoadingStatistics.java +++ b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleLoadingStatistics.java @@ -18,6 +18,7 @@ * @author Arne Seime - Initial contribution */ public class JRuleLoadingStatistics { + private int numStartupTriggers; private int numChannelTriggers; private int numItemStateTriggers; private int numTimedTriggers; @@ -45,6 +46,10 @@ public void addItemStateTrigger() { numItemStateTriggers++; } + public void addStartupTrigger() { + numStartupTriggers++; + } + public void addTimedTrigger() { numTimedTriggers++; } @@ -94,6 +99,11 @@ public String toString() { b.append(String.format("Loaded %d thing triggers, change %d", numThingTriggers, previous == null ? 0 : numThingTriggers - previous.numThingTriggers)); + b.append("\n"); + b.append("******** "); + b.append(String.format("Loaded %d startup triggers, change %d", numStartupTriggers, + previous == null ? 0 : numStartupTriggers - previous.numStartupTriggers)); + int numDisabledRules = numRuleMethods - numEnabledRules; if (numDisabledRules > 0) { diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleStartupExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleStartupExecutionContext.java new file mode 100644 index 00000000..e1ee2d30 --- /dev/null +++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleStartupExecutionContext.java @@ -0,0 +1,58 @@ +/** + * 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.automation.jrule.internal.engine.excutioncontext; + +import java.time.Duration; +import java.util.List; + +import org.openhab.automation.jrule.internal.engine.JRuleInvocationCallback; +import org.openhab.automation.jrule.rules.event.JRuleEvent; +import org.openhab.automation.jrule.rules.event.JRuleStartupEvent; +import org.openhab.core.events.AbstractEvent; +import org.openhab.core.events.system.StartlevelEvent; + +/** + * The {@link JRuleStartupExecutionContext} - execution context for startup triggers + * + * @author Robert Delbrück + */ +public class JRuleStartupExecutionContext extends JRuleExecutionContext { + + private final int startupLevel; + + public JRuleStartupExecutionContext(String uid, String logName, String[] loggingTags, + JRuleInvocationCallback invocationCallback, List preconditionContextList, + Duration timedLock, Duration delayed, int startupLevel) { + super(uid, logName, loggingTags, invocationCallback, preconditionContextList, timedLock, delayed); + this.startupLevel = startupLevel; + } + + @Override + public boolean match(AbstractEvent event, JRuleAdditionalCheckData checkData) { + if (!(event instanceof StartlevelEvent evt)) { + return false; + } + return startupLevel == evt.getStartlevel(); + } + + @Override + public JRuleEvent createJRuleEvent(AbstractEvent event) { + StartlevelEvent startlevelEvent = (StartlevelEvent) event; + + return new JRuleStartupEvent((startlevelEvent).getStartlevel()); + } + + public int getStartupLevel() { + return startupLevel; + } +} diff --git a/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java b/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java index 20ae64c7..85d9231a 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java +++ b/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java @@ -27,6 +27,7 @@ import org.openhab.core.events.Event; import org.openhab.core.events.EventFilter; import org.openhab.core.events.EventSubscriber; +import org.openhab.core.events.system.StartlevelEvent; import org.openhab.core.items.events.GroupItemStateChangedEvent; import org.openhab.core.items.events.ItemAddedEvent; import org.openhab.core.items.events.ItemCommandEvent; @@ -63,6 +64,7 @@ public class JRuleEventSubscriber implements EventSubscriber { public static final String PROPERTY_THING_STATUS_EVENT = "THING_STATUS_EVENT"; private static final String LOG_NAME_SUBSCRIBER = "JRuleSubscriber"; + public static final String PROPERTY_STARTUP_EVENT = "STARTUP_EVENT"; // status changes private final Logger logger = LoggerFactory.getLogger(JRuleEventSubscriber.class); @@ -92,6 +94,7 @@ public JRuleEventSubscriber() { // subscribedEventTypes.add(ThingUpdatedEvent.TYPE); subscribedEventTypes.add(ThingRemovedEvent.TYPE); subscribedEventTypes.add(ThingStatusInfoChangedEvent.TYPE); + subscribedEventTypes.add(StartlevelEvent.TYPE); } @Override @@ -188,6 +191,13 @@ private void processEvent(Event event) { PROPERTY_THING_STATUS_EVENT, event.getTopic(), event.getPayload()); propertyChangeSupport.firePropertyChange(PROPERTY_THING_STATUS_EVENT, null, event); } + } else if (event.getType().equals(StartlevelEvent.TYPE)) { + StartlevelEvent startlevelEvent = (StartlevelEvent) event; + if (jRuleEngine.watchingForStartlevel(startlevelEvent.getStartlevel())) { + JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Event processed as {}: topic {} payload: {}", + PROPERTY_STARTUP_EVENT, event.getTopic(), event.getPayload()); + propertyChangeSupport.firePropertyChange(PROPERTY_STARTUP_EVENT, null, event); + } } } diff --git a/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleEventHandler.java b/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleEventHandler.java index e7a51f3d..cb2bd0d3 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleEventHandler.java +++ b/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleEventHandler.java @@ -12,7 +12,15 @@ */ package org.openhab.automation.jrule.internal.handler; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNull; @@ -24,12 +32,47 @@ import org.openhab.automation.jrule.items.JRuleItem; import org.openhab.automation.jrule.items.JRuleItemRegistry; import org.openhab.automation.jrule.rules.JRule; -import org.openhab.automation.jrule.rules.value.*; +import org.openhab.automation.jrule.rules.value.JRuleDateTimeValue; +import org.openhab.automation.jrule.rules.value.JRuleDecimalValue; +import org.openhab.automation.jrule.rules.value.JRuleHsbValue; +import org.openhab.automation.jrule.rules.value.JRuleNextPreviousValue; +import org.openhab.automation.jrule.rules.value.JRuleOnOffValue; +import org.openhab.automation.jrule.rules.value.JRuleOpenClosedValue; +import org.openhab.automation.jrule.rules.value.JRulePercentValue; +import org.openhab.automation.jrule.rules.value.JRulePlayPauseValue; +import org.openhab.automation.jrule.rules.value.JRulePointValue; +import org.openhab.automation.jrule.rules.value.JRuleQuantityValue; +import org.openhab.automation.jrule.rules.value.JRuleRawValue; +import org.openhab.automation.jrule.rules.value.JRuleRewindFastforwardValue; +import org.openhab.automation.jrule.rules.value.JRuleStopMoveValue; +import org.openhab.automation.jrule.rules.value.JRuleStringListValue; +import org.openhab.automation.jrule.rules.value.JRuleStringValue; +import org.openhab.automation.jrule.rules.value.JRuleUpDownValue; +import org.openhab.automation.jrule.rules.value.JRuleValue; import org.openhab.core.events.EventPublisher; -import org.openhab.core.items.*; +import org.openhab.core.items.GenericItem; +import org.openhab.core.items.GroupItem; +import org.openhab.core.items.Item; +import org.openhab.core.items.ItemNotFoundException; +import org.openhab.core.items.ItemRegistry; import org.openhab.core.items.events.ItemEvent; import org.openhab.core.items.events.ItemEventFactory; -import org.openhab.core.library.types.*; +import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.HSBType; +import org.openhab.core.library.types.NextPreviousType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.OpenClosedType; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.library.types.PlayPauseType; +import org.openhab.core.library.types.PointType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.RawType; +import org.openhab.core.library.types.RewindFastforwardType; +import org.openhab.core.library.types.StopMoveType; +import org.openhab.core.library.types.StringListType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.types.UpDownType; import org.openhab.core.types.Command; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; diff --git a/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleEntry.java b/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleEntry.java index c9ac59df..9bc04c0f 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleEntry.java +++ b/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleEntry.java @@ -23,12 +23,14 @@ import org.openhab.automation.jrule.internal.engine.JRuleEngine; import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleExecutionContext; +import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleStartupExecutionContext; import org.openhab.automation.jrule.rules.JRule; import org.openhab.automation.jrule.rules.JRuleWhenChannelTrigger; import org.openhab.automation.jrule.rules.JRuleWhenCronTrigger; import org.openhab.automation.jrule.rules.JRuleWhenItemChange; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate; +import org.openhab.automation.jrule.rules.JRuleWhenStartup; import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger; import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger; import org.openhab.core.automation.Action; @@ -160,6 +162,14 @@ public void addJRuleWhenThingTrigger(JRuleExecutionContext context) { ruleTriggers.add(triggerBuilder.build()); } + public void addJRuleWhenStartupTrigger(JRuleStartupExecutionContext context) { + executionContextList.add(context); + TriggerBuilder triggerBuilder = TriggerBuilder.create().withId("" + (triggerCounter++)) + .withTypeUID(JRuleModuleUtil.toTriggerModuleUID(JRuleWhenStartup.class)); + + ruleTriggers.add(triggerBuilder.build()); + } + public void addTags(String[] loggingTags) { tags.addAll(Arrays.stream(loggingTags).collect(Collectors.toSet())); } diff --git a/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleHandlerFactory.java b/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleHandlerFactory.java index d1f2f4b2..c142ff72 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleHandlerFactory.java +++ b/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleHandlerFactory.java @@ -22,6 +22,7 @@ import org.openhab.automation.jrule.rules.JRuleWhenItemChange; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate; +import org.openhab.automation.jrule.rules.JRuleWhenStartup; import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger; import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger; import org.openhab.core.automation.Module; @@ -47,7 +48,8 @@ public class JRuleModuleHandlerFactory extends BaseModuleHandlerFactory { JRuleModuleUtil.toTriggerModuleUID(JRuleWhenChannelTrigger.class), JRuleModuleUtil.toTriggerModuleUID(JRuleWhenCronTrigger.class), JRuleModuleUtil.toTriggerModuleUID(JRuleWhenTimeTrigger.class), - JRuleModuleUtil.toTriggerModuleUID(JRuleWhenThingTrigger.class)); + JRuleModuleUtil.toTriggerModuleUID(JRuleWhenThingTrigger.class), + JRuleModuleUtil.toTriggerModuleUID(JRuleWhenStartup.class)); private JRuleRuleProvider jRuleRuleProvider; @Activate diff --git a/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleTypeProvider.java b/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleTypeProvider.java index 69ef7abf..e1158075 100644 --- a/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleTypeProvider.java +++ b/src/main/java/org/openhab/automation/jrule/internal/module/JRuleModuleTypeProvider.java @@ -24,6 +24,7 @@ import org.openhab.automation.jrule.rules.JRuleWhenItemChange; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand; import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate; +import org.openhab.automation.jrule.rules.JRuleWhenStartup; import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger; import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger; import org.openhab.core.automation.type.ModuleType; @@ -52,7 +53,8 @@ public class JRuleModuleTypeProvider implements ModuleTypeProvider { JRuleModuleUtil.toTriggerModuleUID(JRuleWhenTimeTrigger.class), new JRuleTriggerType(JRuleWhenTimeTrigger.class), JRuleModuleUtil.toTriggerModuleUID(JRuleWhenThingTrigger.class), - new JRuleTriggerType(JRuleWhenThingTrigger.class)); + new JRuleTriggerType(JRuleWhenThingTrigger.class), + JRuleModuleUtil.toTriggerModuleUID(JRuleWhenStartup.class), new JRuleTriggerType(JRuleWhenStartup.class)); @SuppressWarnings("unchecked") @Override diff --git a/src/main/java/org/openhab/automation/jrule/items/JRuleColorItem.java b/src/main/java/org/openhab/automation/jrule/items/JRuleColorItem.java index ca06de40..a45b8bde 100644 --- a/src/main/java/org/openhab/automation/jrule/items/JRuleColorItem.java +++ b/src/main/java/org/openhab/automation/jrule/items/JRuleColorItem.java @@ -18,7 +18,7 @@ import org.openhab.automation.jrule.internal.JRuleUtil; import org.openhab.automation.jrule.internal.handler.JRuleEventHandler; import org.openhab.automation.jrule.internal.items.JRuleInternalColorItem; -import org.openhab.automation.jrule.rules.value.*; +import org.openhab.automation.jrule.rules.value.JRuleHsbValue; /** * The {@link JRuleColorItem} JRule Item @@ -36,7 +36,7 @@ static Optional forNameOptional(String itemName) { /** * Sends a hsb command - * + * * @param command command to send. */ default void sendCommand(JRuleHsbValue command) { @@ -45,7 +45,7 @@ default void sendCommand(JRuleHsbValue command) { /** * Sends a hsb update - * + * * @param state update to send */ default void postUpdate(JRuleHsbValue state) { diff --git a/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java b/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java index f5519bf6..84914d5a 100644 --- a/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java +++ b/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java @@ -13,7 +13,11 @@ package org.openhab.automation.jrule.items; import java.time.ZonedDateTime; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.automation.jrule.exception.JRuleItemNotFoundException; @@ -56,7 +60,7 @@ static Optional forNameOptional(String itemName) { /** * Returns all GroupItems, which this item belongs to -> this item is a member of the returning result - * + * * @return GroupItems which this items belongs to */ default Set> getGroupItems() { diff --git a/src/main/java/org/openhab/automation/jrule/items/JRulePlayerItem.java b/src/main/java/org/openhab/automation/jrule/items/JRulePlayerItem.java index 110bb118..2092a1f6 100644 --- a/src/main/java/org/openhab/automation/jrule/items/JRulePlayerItem.java +++ b/src/main/java/org/openhab/automation/jrule/items/JRulePlayerItem.java @@ -18,7 +18,9 @@ import org.openhab.automation.jrule.internal.JRuleUtil; import org.openhab.automation.jrule.internal.handler.JRuleEventHandler; import org.openhab.automation.jrule.internal.items.JRuleInternalPlayerItem; -import org.openhab.automation.jrule.rules.value.*; +import org.openhab.automation.jrule.rules.value.JRuleNextPreviousValue; +import org.openhab.automation.jrule.rules.value.JRulePlayPauseValue; +import org.openhab.automation.jrule.rules.value.JRuleRewindFastforwardValue; /** * The {@link JRulePlayerItem} JRule Item @@ -43,7 +45,7 @@ static Optional forNameOptional(String itemName) { /** * Sends a play/pause command - * + * * @param command command to send. */ default void sendCommand(JRulePlayPauseValue command) { @@ -52,7 +54,7 @@ default void sendCommand(JRulePlayPauseValue command) { /** * Sends a play/pause update - * + * * @param state update to send */ default void postUpdate(JRulePlayPauseValue state) { diff --git a/src/main/java/org/openhab/automation/jrule/items/JRuleRollershutterItem.java b/src/main/java/org/openhab/automation/jrule/items/JRuleRollershutterItem.java index 4108b76d..79a5befc 100644 --- a/src/main/java/org/openhab/automation/jrule/items/JRuleRollershutterItem.java +++ b/src/main/java/org/openhab/automation/jrule/items/JRuleRollershutterItem.java @@ -19,7 +19,9 @@ import org.openhab.automation.jrule.internal.JRuleUtil; import org.openhab.automation.jrule.internal.handler.JRuleEventHandler; import org.openhab.automation.jrule.internal.items.JRuleInternalRollershutterItem; -import org.openhab.automation.jrule.rules.value.*; +import org.openhab.automation.jrule.rules.value.JRulePercentValue; +import org.openhab.automation.jrule.rules.value.JRuleStopMoveValue; +import org.openhab.automation.jrule.rules.value.JRuleUpDownValue; /** * The {@link JRuleRollershutterItem} JRule Item @@ -42,7 +44,7 @@ static Optional forNameOptional(String itemName) { /** * Sends a percent command - * + * * @param command command to send. */ default void sendCommand(JRulePercentValue command) { @@ -51,7 +53,7 @@ default void sendCommand(JRulePercentValue command) { /** * Sends a percent update - * + * * @param state update to send */ default void postUpdate(JRulePercentValue state) { @@ -60,7 +62,7 @@ default void postUpdate(JRulePercentValue state) { /** * Sends a percent command. - * + * * @param command as number via JRulePercentValue will be send. */ default void sendCommand(int command) { @@ -96,7 +98,7 @@ default void sendCommand(JRuleStopMoveValue command) { /** * Sends a percent update. - * + * * @param state as number via JRulePercentValue will be send. */ default void postUpdate(int state) { diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenStartup.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenStartup.java new file mode 100644 index 00000000..9dfbc654 --- /dev/null +++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenStartup.java @@ -0,0 +1,31 @@ +/** + * 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.automation.jrule.rules; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@link JRuleWhenStartup} + * + * @author Robert Delbrück + */ +@Repeatable(JRuleWhenStartups.class) +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface JRuleWhenStartup { + int level() default 100; +} diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenStartups.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenStartups.java new file mode 100644 index 00000000..22827468 --- /dev/null +++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenStartups.java @@ -0,0 +1,29 @@ +/** + * 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.automation.jrule.rules; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@link JRuleWhenStartups} + * + * @author Robert Delbrück + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface JRuleWhenStartups { + JRuleWhenStartup[] value(); +} diff --git a/src/main/java/org/openhab/automation/jrule/rules/event/JRuleStartupEvent.java b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleStartupEvent.java new file mode 100644 index 00000000..653a2b58 --- /dev/null +++ b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleStartupEvent.java @@ -0,0 +1,35 @@ +/** + * 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.automation.jrule.rules.event; + +/** + * The {@link JRuleStartupEvent} + * + * @author Robert Delbrück + */ +public class JRuleStartupEvent extends JRuleEvent { + private final int startupLevel; + + public JRuleStartupEvent(int startupLevel) { + this.startupLevel = startupLevel; + } + + public int getStartupLevel() { + return startupLevel; + } + + @Override + public String toString() { + return "JRuleStartupEvent{" + "startupLevel=" + startupLevel + '}'; + } +} diff --git a/src/test/java/org/openhab/automation/jrule/internal/engine/JRuleBuilderTest.java b/src/test/java/org/openhab/automation/jrule/internal/engine/JRuleBuilderTest.java index 2d80cff6..79627f50 100644 --- a/src/test/java/org/openhab/automation/jrule/internal/engine/JRuleBuilderTest.java +++ b/src/test/java/org/openhab/automation/jrule/internal/engine/JRuleBuilderTest.java @@ -27,13 +27,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.openhab.automation.jrule.internal.engine.JRuleBuilder.Condition; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleChannelExecutionContext; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemChangeExecutionContext; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedCommandExecutionContext; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedUpdateExecutionContext; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimeTimerExecutionContext; -import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedCronExecutionContext; +import org.openhab.automation.jrule.internal.engine.excutioncontext.*; import org.openhab.automation.jrule.internal.module.JRuleRuleProvider; import org.openhab.automation.jrule.internal.rules.JRuleAbstractTest; import org.openhab.automation.jrule.rules.JRuleMemberOf; @@ -206,6 +200,16 @@ public void testPreconditions() { verify(ruleProvider, times(1)).add(argThat(entry -> entry.getTriggers().size() == 1)); } + @Test + public void testWhenStartupTrigger() { + + boolean result = jRuleBuilder.whenStartupTrigger(10).whenStartupTrigger(30).build(); + + Assertions.assertTrue(result); + verify(jRuleEngine, times(2)).addToContext(isA(JRuleStartupExecutionContext.class), eq(false)); + verify(ruleProvider, times(1)).add(argThat(entry -> entry.getTriggers().size() == 2)); + } + @Test public void testWhenThingTrigger() { diff --git a/src/test/java/org/openhab/automation/jrule/items/JRuleUnspecifiedGroupItemTest.java b/src/test/java/org/openhab/automation/jrule/items/JRuleUnspecifiedGroupItemTest.java index 8f562494..70814de4 100644 --- a/src/test/java/org/openhab/automation/jrule/items/JRuleUnspecifiedGroupItemTest.java +++ b/src/test/java/org/openhab/automation/jrule/items/JRuleUnspecifiedGroupItemTest.java @@ -12,7 +12,9 @@ */ package org.openhab.automation.jrule.items; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/openhab/automation/jrule/rules/integration_test/ITJRule.java b/src/test/java/org/openhab/automation/jrule/rules/integration_test/ITJRule.java index 5ea66a3e..2a943a97 100644 --- a/src/test/java/org/openhab/automation/jrule/rules/integration_test/ITJRule.java +++ b/src/test/java/org/openhab/automation/jrule/rules/integration_test/ITJRule.java @@ -285,4 +285,11 @@ public void triggerOnGroupStateChange() throws IOException { verifyLogEntry("rule trigger for change: OFF"); verifyNoError(); } + + @Test + public void startupTriggered() throws IOException { + verifyRuleWasExecuted(TestRules.NAME_STARTUP_TRIGGERED); + verifyLogEntry("Startup Event: '50'"); + verifyNoError(); + } } diff --git a/src/test/java/org/openhab/automation/jrule/rules/integration_test/JRuleITBase.java b/src/test/java/org/openhab/automation/jrule/rules/integration_test/JRuleITBase.java index 5d083903..872cf01b 100644 --- a/src/test/java/org/openhab/automation/jrule/rules/integration_test/JRuleITBase.java +++ b/src/test/java/org/openhab/automation/jrule/rules/integration_test/JRuleITBase.java @@ -32,7 +32,12 @@ import org.awaitility.Awaitility; import org.eclipse.paho.client.mqttv3.*; import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInfo; import org.openhab.automation.jrule.items.JRuleSwitchItem; import org.openhab.automation.jrule.rules.user.TestRules; import org.slf4j.Logger; diff --git a/src/test/java/org/openhab/automation/jrule/rules/user/TestPersistence.java b/src/test/java/org/openhab/automation/jrule/rules/user/TestPersistence.java index d2f49073..1f27dc50 100755 --- a/src/test/java/org/openhab/automation/jrule/rules/user/TestPersistence.java +++ b/src/test/java/org/openhab/automation/jrule/rules/user/TestPersistence.java @@ -19,9 +19,24 @@ import java.util.function.BiFunction; import java.util.function.Function; -import org.openhab.automation.jrule.items.*; -import org.openhab.automation.jrule.rules.*; -import org.openhab.automation.jrule.rules.value.*; +import org.openhab.automation.jrule.items.JRuleColorItem; +import org.openhab.automation.jrule.items.JRuleContactItem; +import org.openhab.automation.jrule.items.JRuleDateTimeItem; +import org.openhab.automation.jrule.items.JRuleDimmerItem; +import org.openhab.automation.jrule.items.JRuleImageItem; +import org.openhab.automation.jrule.items.JRuleItem; +import org.openhab.automation.jrule.items.JRuleLocationItem; +import org.openhab.automation.jrule.items.JRuleNumberItem; +import org.openhab.automation.jrule.items.JRulePlayerItem; +import org.openhab.automation.jrule.items.JRuleQuantityItem; +import org.openhab.automation.jrule.items.JRuleRollershutterItem; +import org.openhab.automation.jrule.items.JRuleStringItem; +import org.openhab.automation.jrule.items.JRuleSwitchItem; +import org.openhab.automation.jrule.rules.JRule; +import org.openhab.automation.jrule.rules.JRuleCondition; +import org.openhab.automation.jrule.rules.JRuleName; +import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand; +import org.openhab.automation.jrule.rules.value.JRuleDecimalValue; /** * The {@link TestPersistence} diff --git a/src/test/java/org/openhab/automation/jrule/rules/user/TestRules.java b/src/test/java/org/openhab/automation/jrule/rules/user/TestRules.java index 0ead8a28..61a69d9e 100755 --- a/src/test/java/org/openhab/automation/jrule/rules/user/TestRules.java +++ b/src/test/java/org/openhab/automation/jrule/rules/user/TestRules.java @@ -28,14 +28,53 @@ import java.util.stream.Collectors; import org.openhab.automation.jrule.exception.JRuleExecutionException; -import org.openhab.automation.jrule.items.*; +import org.openhab.automation.jrule.items.JRuleColorItem; +import org.openhab.automation.jrule.items.JRuleContactItem; +import org.openhab.automation.jrule.items.JRuleDateTimeItem; +import org.openhab.automation.jrule.items.JRuleDimmerItem; +import org.openhab.automation.jrule.items.JRuleGroupItem; +import org.openhab.automation.jrule.items.JRuleImageItem; +import org.openhab.automation.jrule.items.JRuleItem; +import org.openhab.automation.jrule.items.JRuleLocationItem; +import org.openhab.automation.jrule.items.JRuleNumberGroupItem; +import org.openhab.automation.jrule.items.JRuleNumberItem; +import org.openhab.automation.jrule.items.JRulePlayerItem; +import org.openhab.automation.jrule.items.JRuleQuantityItem; +import org.openhab.automation.jrule.items.JRuleRollershutterItem; +import org.openhab.automation.jrule.items.JRuleStringItem; +import org.openhab.automation.jrule.items.JRuleSwitchGroupItem; +import org.openhab.automation.jrule.items.JRuleSwitchItem; import org.openhab.automation.jrule.items.metadata.JRuleItemMetadata; -import org.openhab.automation.jrule.rules.*; +import org.openhab.automation.jrule.rules.JRule; +import org.openhab.automation.jrule.rules.JRuleCondition; +import org.openhab.automation.jrule.rules.JRuleDebounce; +import org.openhab.automation.jrule.rules.JRuleMemberOf; +import org.openhab.automation.jrule.rules.JRuleName; +import org.openhab.automation.jrule.rules.JRulePrecondition; +import org.openhab.automation.jrule.rules.JRuleTag; +import org.openhab.automation.jrule.rules.JRuleWhenChannelTrigger; +import org.openhab.automation.jrule.rules.JRuleWhenCronTrigger; +import org.openhab.automation.jrule.rules.JRuleWhenItemChange; +import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand; +import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate; +import org.openhab.automation.jrule.rules.JRuleWhenStartup; +import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger; import org.openhab.automation.jrule.rules.event.JRuleChannelEvent; import org.openhab.automation.jrule.rules.event.JRuleItemEvent; +import org.openhab.automation.jrule.rules.event.JRuleStartupEvent; import org.openhab.automation.jrule.rules.event.JRuleThingEvent; import org.openhab.automation.jrule.rules.event.JRuleTimerEvent; -import org.openhab.automation.jrule.rules.value.*; +import org.openhab.automation.jrule.rules.value.JRuleDecimalValue; +import org.openhab.automation.jrule.rules.value.JRuleHsbValue; +import org.openhab.automation.jrule.rules.value.JRuleOnOffValue; +import org.openhab.automation.jrule.rules.value.JRuleOpenClosedValue; +import org.openhab.automation.jrule.rules.value.JRulePercentValue; +import org.openhab.automation.jrule.rules.value.JRulePlayPauseValue; +import org.openhab.automation.jrule.rules.value.JRulePointValue; +import org.openhab.automation.jrule.rules.value.JRuleQuantityValue; +import org.openhab.automation.jrule.rules.value.JRuleRawValue; +import org.openhab.automation.jrule.rules.value.JRuleStringValue; +import org.openhab.automation.jrule.rules.value.JRuleUpDownValue; import org.openhab.automation.jrule.things.JRuleThingStatus; /** @@ -118,6 +157,9 @@ public class TestRules extends JRule { public static final String NAME_TRIGGER_ON_GROUP_STATE_CHANGE = "trigger on group state change"; public static final String ITEM_SWITCH_GROUP_OR = "SwitchGroupOr"; public static final String TAG_CUSTOM = "custom"; + public static final String NAME_STARTUP_TRIGGERED = "startup triggered"; + + private boolean startupTriggerWasCalled; @JRuleTag({ TAG_CUSTOM }) @JRuleName(NAME_SWITCH_ITEM_RECEIVED_ANY_COMMAND) @@ -216,6 +258,7 @@ public synchronized void conditionLteAndGteForNumber(JRuleItemEvent event) { @JRuleWhenCronTrigger(cron = "*/5 * * * * *") public void cronEvery5Sec(JRuleTimerEvent event) { logInfo("cron triggered", event); + logInfo("startup level 50 triggered: {}", startupTriggerWasCalled); } @JRulePrecondition(item = ITEM_PRECONDITION_STRING, condition = @JRuleCondition(eq = "that matches")) @@ -397,6 +440,13 @@ public void getTagsAndMetadata() { logInfo("Metadata Configuration: '{}'", item.getMetadata().get("VoiceSystem").getConfiguration()); } + @JRuleName(NAME_STARTUP_TRIGGERED) + @JRuleWhenStartup(level = 50) + public void startupTriggered(JRuleStartupEvent evt) { + startupTriggerWasCalled = true; + logInfo("Startup Event: '{}'", evt.getStartupLevel()); + } + private static void castLocation() { JRuleLocationItem locationItem = JRuleLocationItem.forName(ITEM_LOCATION_TO_CAST); diff --git a/src/test/java/org/openhab/automation/jrule/test_utils/JRuleItemTestUtils.java b/src/test/java/org/openhab/automation/jrule/test_utils/JRuleItemTestUtils.java index 36168b5d..62c81917 100644 --- a/src/test/java/org/openhab/automation/jrule/test_utils/JRuleItemTestUtils.java +++ b/src/test/java/org/openhab/automation/jrule/test_utils/JRuleItemTestUtils.java @@ -22,14 +22,62 @@ import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.mockito.Mockito; -import org.openhab.automation.jrule.items.*; +import org.openhab.automation.jrule.items.JRuleCallGroupItem; +import org.openhab.automation.jrule.items.JRuleCallItem; +import org.openhab.automation.jrule.items.JRuleColorGroupItem; +import org.openhab.automation.jrule.items.JRuleColorItem; +import org.openhab.automation.jrule.items.JRuleContactGroupItem; +import org.openhab.automation.jrule.items.JRuleContactItem; +import org.openhab.automation.jrule.items.JRuleDateTimeItem; +import org.openhab.automation.jrule.items.JRuleDimmerGroupItem; +import org.openhab.automation.jrule.items.JRuleDimmerItem; +import org.openhab.automation.jrule.items.JRuleImageGroupItem; +import org.openhab.automation.jrule.items.JRuleImageItem; +import org.openhab.automation.jrule.items.JRuleItem; +import org.openhab.automation.jrule.items.JRuleLocationGroupItem; +import org.openhab.automation.jrule.items.JRuleLocationItem; +import org.openhab.automation.jrule.items.JRuleNumberGroupItem; +import org.openhab.automation.jrule.items.JRuleNumberItem; +import org.openhab.automation.jrule.items.JRulePlayerGroupItem; +import org.openhab.automation.jrule.items.JRulePlayerItem; +import org.openhab.automation.jrule.items.JRuleQuantityGroupItem; +import org.openhab.automation.jrule.items.JRuleQuantityItem; +import org.openhab.automation.jrule.items.JRuleRollershutterGroupItem; +import org.openhab.automation.jrule.items.JRuleRollershutterItem; +import org.openhab.automation.jrule.items.JRuleStringGroupItem; +import org.openhab.automation.jrule.items.JRuleStringItem; +import org.openhab.automation.jrule.items.JRuleSwitchGroupItem; +import org.openhab.automation.jrule.items.JRuleSwitchItem; +import org.openhab.automation.jrule.items.JRuleUnspecifiedGroupItem; import org.openhab.core.i18n.UnitProvider; import org.openhab.core.internal.i18n.I18nProviderImpl; import org.openhab.core.items.GenericItem; import org.openhab.core.items.GroupItem; import org.openhab.core.items.Item; -import org.openhab.core.library.items.*; -import org.openhab.core.library.types.*; +import org.openhab.core.library.items.CallItem; +import org.openhab.core.library.items.ColorItem; +import org.openhab.core.library.items.ContactItem; +import org.openhab.core.library.items.DateTimeItem; +import org.openhab.core.library.items.DimmerItem; +import org.openhab.core.library.items.ImageItem; +import org.openhab.core.library.items.LocationItem; +import org.openhab.core.library.items.NumberItem; +import org.openhab.core.library.items.PlayerItem; +import org.openhab.core.library.items.RollershutterItem; +import org.openhab.core.library.items.StringItem; +import org.openhab.core.library.items.SwitchItem; +import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.HSBType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.OpenClosedType; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.library.types.PlayPauseType; +import org.openhab.core.library.types.PointType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.RawType; +import org.openhab.core.library.types.StringListType; +import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.Units; import org.openhab.core.types.State; import org.osgi.framework.BundleContext;