From 64a31026cd871f752cb296a5581a8d26d24c040d Mon Sep 17 00:00:00 2001 From: J-N-K Date: Sun, 13 Nov 2022 10:50:42 +0100 Subject: [PATCH] Add unmanaged scripts to rule engine (#3156) Signed-off-by: Jan N. Klug --- .../openhab/core/automation/RuleManager.java | 20 ++++++----- .../automation/internal/RuleEngineImpl.java | 30 +++++++--------- .../runtime/internal/DSLRuleProvider.java | 36 +++++++++++++++++++ 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/RuleManager.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/RuleManager.java index 899abbe208..320926a191 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/RuleManager.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/RuleManager.java @@ -35,12 +35,14 @@ public interface RuleManager { * This method gets enabled {@link RuleStatus} for a {@link Rule}. * The enabled rule statuses are {@link RuleStatus#UNINITIALIZED}, {@link RuleStatus#IDLE} and * {@link RuleStatus#RUNNING}. - * The disabled rule status is {@link RuleStatus#DISABLED}. + * The disabled rule status is {@link RuleStatus#UNINITIALIZED} with {@link RuleStatusDetail#DISABLED}. * * @param ruleUID UID of the {@link Rule} - * @return {@code true} when the {@link RuleStatus} is one of the {@link RuleStatus#UNINITIALIZED}, + * @return {@code true} when the {@link RuleStatus} is one of the {@link RuleStatus#UNINITIALIZED} with any other + * {@link RuleStatusDetail} than {@link RuleStatusDetail#DISABLED}, * {@link RuleStatus#IDLE} and {@link RuleStatus#RUNNING}, {@code false} when it is - * {@link RuleStatus#DISABLED} and {@code null} when it is not available. + * {@link RuleStatus#UNINITIALIZED} with {@link RuleStatusDetail#DISABLED} and {@code null} when it is not + * available. */ @Nullable Boolean isEnabled(String ruleUID); @@ -49,7 +51,7 @@ public interface RuleManager { * This method is used for changing enabled state of the {@link Rule}. * The enabled rule statuses are {@link RuleStatus#UNINITIALIZED}, {@link RuleStatus#IDLE} and * {@link RuleStatus#RUNNING}. - * The disabled rule status is {@link RuleStatus#DISABLED}. + * The disabled rule status is {@link RuleStatus#UNINITIALIZED} with {@link RuleStatusDetail#DISABLED}. * * @param uid the unique identifier of the {@link Rule}. * @param isEnabled a new enabled / disabled state of the {@link Rule}. @@ -81,19 +83,21 @@ public interface RuleManager { * This should always be possible unless an action has a mandatory input that is linked to a trigger. * In that case the action is skipped and the rule engine continues execution of rest actions. * - * @param ruleUID id of the rule whose actions have to be executed. + * @param uid id of the rule whose actions have to be executed. + * @return a copy of the rule context, including possible return values */ - void runNow(String uid); + Map runNow(String uid); /** * Same as {@link #runNow(String)} with the additional option to enable/disable evaluation of * conditions defined in the target rule. The context can be set here, too, but also might be {@code null}. * - * @param ruleUID id of the rule whose actions have to be executed. + * @param uid id of the rule whose actions have to be executed. * @param considerConditions if {@code true} the conditions of the rule will be checked. * @param context the context that is passed to the conditions and the actions of the rule. + * @return a copy of the rule context, including possible return values */ - void runNow(String uid, boolean considerConditions, @Nullable Map context); + Map runNow(String uid, boolean considerConditions, @Nullable Map context); /** * Simulates the execution of all rules with tag 'Schedule' for the given time interval. diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/RuleEngineImpl.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/RuleEngineImpl.java index eafcc455a1..f0b58e278b 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/RuleEngineImpl.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/RuleEngineImpl.java @@ -440,7 +440,7 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener context) { + public Map runNow(String ruleUID, boolean considerConditions, + @Nullable Map context) { + Map returnContext = new HashMap<>(); final WrappedRule rule = getManagedRule(ruleUID); if (rule == null) { logger.warn("Failed to execute rule '{}': Invalid Rule UID", ruleUID); - return; + return returnContext; } synchronized (this) { final RuleStatus ruleStatus = getRuleStatus(ruleUID); if (ruleStatus != null && ruleStatus != RuleStatus.IDLE) { logger.error("Failed to execute rule ‘{}' with status '{}'", ruleUID, ruleStatus.name()); - return; + return returnContext; } // change state to RUNNING setStatus(ruleUID, new RuleStatusInfo(RuleStatus.RUNNING)); @@ -1025,14 +1027,11 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener runNow(String ruleUID) { + return runNow(ruleUID, false, null); } /** @@ -1092,11 +1092,7 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener getContext(String ruleUID, @Nullable Set connections) { - Map context = contextMap.get(ruleUID); - if (context == null) { - context = new HashMap<>(); - contextMap.put(ruleUID, context); - } + Map context = contextMap.computeIfAbsent(ruleUID, k -> new HashMap<>()); if (connections != null) { StringBuffer sb = new StringBuffer(); for (Connection c : connections) { diff --git a/bundles/org.openhab.core.model.rule.runtime/src/org/openhab/core/model/rule/runtime/internal/DSLRuleProvider.java b/bundles/org.openhab.core.model.rule.runtime/src/org/openhab/core/model/rule/runtime/internal/DSLRuleProvider.java index e53ec306b8..7b3aebc14d 100644 --- a/bundles/org.openhab.core.model.rule.runtime/src/org/openhab/core/model/rule/runtime/internal/DSLRuleProvider.java +++ b/bundles/org.openhab.core.model.rule.runtime/src/org/openhab/core/model/rule/runtime/internal/DSLRuleProvider.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.emf.ecore.EObject; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -58,6 +59,7 @@ import org.openhab.core.model.rule.rules.TimerTrigger; import org.openhab.core.model.rule.rules.DateTimeTrigger; import org.openhab.core.model.rule.rules.UpdateEventTrigger; import org.openhab.core.model.script.runtime.DSLScriptContextProvider; +import org.openhab.core.model.script.script.Script; import org.openhab.core.service.ReadyMarker; import org.openhab.core.service.ReadyMarkerFilter; import org.openhab.core.service.ReadyService; @@ -170,6 +172,28 @@ public class DSLRuleProvider default: logger.debug("Unknown event type."); } + } else if ("script".equals(ruleModelType)) { + switch (type) { + case MODIFIED: + Rule oldRule = rules.remove(modelFileName); + if (oldRule != null) { + removeRule(oldRule); + } + case ADDED: + EObject model = modelRepository.getModel(modelFileName); + if (model instanceof Script) { + addRule(toRule(modelFileName, ((Script) model))); + } + break; + case REMOVED: + oldRule = rules.remove(modelFileName); + if (oldRule != null) { + removeRule(oldRule); + } + break; + default: + logger.debug("Unknown event type."); + } } } @@ -244,6 +268,18 @@ public class DSLRuleProvider } } + private Rule toRule(String modelName, Script script) { + String scriptText = NodeModelUtils.findActualNodeFor(script).getText(); + + Configuration cfg = new Configuration(); + cfg.put("script", removeIndentation(scriptText)); + cfg.put("type", MIMETYPE_OPENHAB_DSL_RULE); + List actions = List.of(ActionBuilder.create().withId("script").withTypeUID("script.ScriptAction") + .withConfiguration(cfg).build()); + + return RuleBuilder.create(modelName).withTags("Script").withName(modelName).withActions(actions).build(); + } + private Rule toRule(String modelName, org.openhab.core.model.rule.rules.Rule rule, int index) { String name = rule.getName(); String uid = modelName + "-" + index;