mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-25 11:45:49 +01:00
Add unmanaged scripts to rule engine (#3156)
Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
parent
d4ceca9fe0
commit
64a31026cd
@ -35,12 +35,14 @@ public interface RuleManager {
|
|||||||
* This method gets <b>enabled</b> {@link RuleStatus} for a {@link Rule}.
|
* This method gets <b>enabled</b> {@link RuleStatus} for a {@link Rule}.
|
||||||
* The <b>enabled</b> rule statuses are {@link RuleStatus#UNINITIALIZED}, {@link RuleStatus#IDLE} and
|
* The <b>enabled</b> rule statuses are {@link RuleStatus#UNINITIALIZED}, {@link RuleStatus#IDLE} and
|
||||||
* {@link RuleStatus#RUNNING}.
|
* {@link RuleStatus#RUNNING}.
|
||||||
* The <b>disabled</b> rule status is {@link RuleStatus#DISABLED}.
|
* The <b>disabled</b> rule status is {@link RuleStatus#UNINITIALIZED} with {@link RuleStatusDetail#DISABLED}.
|
||||||
*
|
*
|
||||||
* @param ruleUID UID of the {@link Rule}
|
* @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#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
|
@Nullable
|
||||||
Boolean isEnabled(String ruleUID);
|
Boolean isEnabled(String ruleUID);
|
||||||
@ -49,7 +51,7 @@ public interface RuleManager {
|
|||||||
* This method is used for changing <b>enabled</b> state of the {@link Rule}.
|
* This method is used for changing <b>enabled</b> state of the {@link Rule}.
|
||||||
* The <b>enabled</b> rule statuses are {@link RuleStatus#UNINITIALIZED}, {@link RuleStatus#IDLE} and
|
* The <b>enabled</b> rule statuses are {@link RuleStatus#UNINITIALIZED}, {@link RuleStatus#IDLE} and
|
||||||
* {@link RuleStatus#RUNNING}.
|
* {@link RuleStatus#RUNNING}.
|
||||||
* The <b>disabled</b> rule status is {@link RuleStatus#DISABLED}.
|
* The <b>disabled</b> rule status is {@link RuleStatus#UNINITIALIZED} with {@link RuleStatusDetail#DISABLED}.
|
||||||
*
|
*
|
||||||
* @param uid the unique identifier of the {@link Rule}.
|
* @param uid the unique identifier of the {@link Rule}.
|
||||||
* @param isEnabled a new <b>enabled / disabled</b> state of the {@link Rule}.
|
* @param isEnabled a new <b>enabled / disabled</b> 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.
|
* 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.
|
* 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<String, Object> runNow(String uid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #runNow(String)} with the additional option to enable/disable evaluation of
|
* 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}.
|
* 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 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.
|
* @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<String, Object> context);
|
Map<String, Object> runNow(String uid, boolean considerConditions, @Nullable Map<String, Object> context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates the execution of all rules with tag 'Schedule' for the given time interval.
|
* Simulates the execution of all rules with tag 'Schedule' for the given time interval.
|
||||||
|
@ -440,7 +440,7 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener<Modul
|
|||||||
/**
|
/**
|
||||||
* This method add a new rule into rule engine. Scope identity of the Rule is the identity of the caller.
|
* This method add a new rule into rule engine. Scope identity of the Rule is the identity of the caller.
|
||||||
*
|
*
|
||||||
* @param rule a rule which has to be added.
|
* @param newRule a rule which has to be added.
|
||||||
*/
|
*/
|
||||||
protected void addRule(Rule newRule) {
|
protected void addRule(Rule newRule) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
@ -587,7 +587,7 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener<Modul
|
|||||||
* Gets {@link TriggerHandlerCallback} for passed {@link Rule}. If it does not exists, a callback object is
|
* Gets {@link TriggerHandlerCallback} for passed {@link Rule}. If it does not exists, a callback object is
|
||||||
* created.
|
* created.
|
||||||
*
|
*
|
||||||
* @param rule rule object for which the callback is looking for.
|
* @param ruleUID rule object for which the callback is looking for.
|
||||||
* @return a {@link TriggerHandlerCallback} corresponding to the passed {@link Rule} object.
|
* @return a {@link TriggerHandlerCallback} corresponding to the passed {@link Rule} object.
|
||||||
*/
|
*/
|
||||||
private synchronized TriggerHandlerCallbackImpl getTriggerHandlerCallback(String ruleUID) {
|
private synchronized TriggerHandlerCallbackImpl getTriggerHandlerCallback(String ruleUID) {
|
||||||
@ -1005,17 +1005,19 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener<Modul
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runNow(String ruleUID, boolean considerConditions, @Nullable Map<String, Object> context) {
|
public Map<String, Object> runNow(String ruleUID, boolean considerConditions,
|
||||||
|
@Nullable Map<String, Object> context) {
|
||||||
|
Map<String, Object> returnContext = new HashMap<>();
|
||||||
final WrappedRule rule = getManagedRule(ruleUID);
|
final WrappedRule rule = getManagedRule(ruleUID);
|
||||||
if (rule == null) {
|
if (rule == null) {
|
||||||
logger.warn("Failed to execute rule '{}': Invalid Rule UID", ruleUID);
|
logger.warn("Failed to execute rule '{}': Invalid Rule UID", ruleUID);
|
||||||
return;
|
return returnContext;
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
final RuleStatus ruleStatus = getRuleStatus(ruleUID);
|
final RuleStatus ruleStatus = getRuleStatus(ruleUID);
|
||||||
if (ruleStatus != null && ruleStatus != RuleStatus.IDLE) {
|
if (ruleStatus != null && ruleStatus != RuleStatus.IDLE) {
|
||||||
logger.error("Failed to execute rule ‘{}' with status '{}'", ruleUID, ruleStatus.name());
|
logger.error("Failed to execute rule ‘{}' with status '{}'", ruleUID, ruleStatus.name());
|
||||||
return;
|
return returnContext;
|
||||||
}
|
}
|
||||||
// change state to RUNNING
|
// change state to RUNNING
|
||||||
setStatus(ruleUID, new RuleStatusInfo(RuleStatus.RUNNING));
|
setStatus(ruleUID, new RuleStatusInfo(RuleStatus.RUNNING));
|
||||||
@ -1025,14 +1027,11 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener<Modul
|
|||||||
if (context != null && !context.isEmpty()) {
|
if (context != null && !context.isEmpty()) {
|
||||||
getContext(ruleUID, null).putAll(context);
|
getContext(ruleUID, null).putAll(context);
|
||||||
}
|
}
|
||||||
if (considerConditions) {
|
if (!considerConditions || calculateConditions(rule)) {
|
||||||
if (calculateConditions(rule)) {
|
|
||||||
executeActions(rule, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
executeActions(rule, false);
|
executeActions(rule, false);
|
||||||
}
|
}
|
||||||
logger.debug("The rule '{}' is executed.", ruleUID);
|
logger.debug("The rule '{}' is executed.", ruleUID);
|
||||||
|
returnContext.putAll(getContext(ruleUID, null));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error("Failed to execute rule '{}': ", ruleUID, t);
|
logger.error("Failed to execute rule '{}': ", ruleUID, t);
|
||||||
}
|
}
|
||||||
@ -1042,11 +1041,12 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener<Modul
|
|||||||
setStatus(ruleUID, new RuleStatusInfo(RuleStatus.IDLE));
|
setStatus(ruleUID, new RuleStatusInfo(RuleStatus.IDLE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return returnContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runNow(String ruleUID) {
|
public Map<String, Object> runNow(String ruleUID) {
|
||||||
runNow(ruleUID, false, null);
|
return runNow(ruleUID, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1092,11 +1092,7 @@ public class RuleEngineImpl implements RuleManager, RegistryChangeListener<Modul
|
|||||||
* @return copy of current context in rule engine
|
* @return copy of current context in rule engine
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> getContext(String ruleUID, @Nullable Set<Connection> connections) {
|
private Map<String, Object> getContext(String ruleUID, @Nullable Set<Connection> connections) {
|
||||||
Map<String, Object> context = contextMap.get(ruleUID);
|
Map<String, Object> context = contextMap.computeIfAbsent(ruleUID, k -> new HashMap<>());
|
||||||
if (context == null) {
|
|
||||||
context = new HashMap<>();
|
|
||||||
contextMap.put(ruleUID, context);
|
|
||||||
}
|
|
||||||
if (connections != null) {
|
if (connections != null) {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
for (Connection c : connections) {
|
for (Connection c : connections) {
|
||||||
|
@ -20,6 +20,7 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.eclipse.emf.ecore.EObject;
|
import org.eclipse.emf.ecore.EObject;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
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.DateTimeTrigger;
|
||||||
import org.openhab.core.model.rule.rules.UpdateEventTrigger;
|
import org.openhab.core.model.rule.rules.UpdateEventTrigger;
|
||||||
import org.openhab.core.model.script.runtime.DSLScriptContextProvider;
|
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.ReadyMarker;
|
||||||
import org.openhab.core.service.ReadyMarkerFilter;
|
import org.openhab.core.service.ReadyMarkerFilter;
|
||||||
import org.openhab.core.service.ReadyService;
|
import org.openhab.core.service.ReadyService;
|
||||||
@ -170,6 +172,28 @@ public class DSLRuleProvider
|
|||||||
default:
|
default:
|
||||||
logger.debug("Unknown event type.");
|
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<Action> 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) {
|
private Rule toRule(String modelName, org.openhab.core.model.rule.rules.Rule rule, int index) {
|
||||||
String name = rule.getName();
|
String name = rule.getName();
|
||||||
String uid = modelName + "-" + index;
|
String uid = modelName + "-" + index;
|
||||||
|
Loading…
Reference in New Issue
Block a user