[automation] Provide triggering item name in the rule context (#1770)

* introduced implicit variable "triggeringItemName"

Fixes #1768

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-12-01 20:29:50 +01:00
committed by GitHub
parent cd0654806b
commit c5f133b3e9
10 changed files with 109 additions and 71 deletions
@@ -40,6 +40,7 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.eclipse.xtext.common.types.JvmFormalParameter
import org.eclipse.emf.common.util.EList
import org.openhab.core.events.Event
/**
* <p>Infers a JVM model from the source model.</p>
@@ -132,6 +133,8 @@ class RulesJvmModelInferrer extends ScriptJvmModelInferrer {
if ((containsCommandTrigger(rule)) || (containsStateChangeTrigger(rule)) || (containsStateUpdateTrigger(rule))) {
val itemTypeRef = ruleModel.newTypeRef(Item)
parameters += rule.toParameter(VAR_TRIGGERING_ITEM, itemTypeRef)
val itemNameRef = ruleModel.newTypeRef(String)
parameters += rule.toParameter(VAR_TRIGGERING_ITEM_NAME, itemNameRef)
}
if (containsCommandTrigger(rule)) {
val commandTypeRef = ruleModel.newTypeRef(Command)
@@ -142,7 +145,7 @@ class RulesJvmModelInferrer extends ScriptJvmModelInferrer {
parameters += rule.toParameter(VAR_PREVIOUS_STATE, stateTypeRef)
}
if (containsEventTrigger(rule)) {
val eventTypeRef = ruleModel.newTypeRef(ChannelTriggeredEvent)
val eventTypeRef = ruleModel.newTypeRef(String)
parameters += rule.toParameter(VAR_RECEIVED_EVENT, eventTypeRef)
}
if (containsThingStateChangedEventTrigger(rule) && !containsParam(parameters, VAR_PREVIOUS_STATE)) {
@@ -31,10 +31,13 @@ import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.interpreter.IEvaluationContext;
import org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationContext;
import org.openhab.core.items.events.ItemEvent;
import org.openhab.core.model.script.engine.Script;
import org.openhab.core.model.script.engine.ScriptExecutionException;
import org.openhab.core.model.script.engine.ScriptParsingException;
import org.openhab.core.model.script.jvmmodel.ScriptJvmModelInferrer;
import org.openhab.core.model.script.runtime.DSLScriptContextProvider;
import org.openhab.core.thing.events.ChannelTriggeredEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,11 +54,14 @@ import org.slf4j.LoggerFactory;
*/
public class DSLScriptEngine implements javax.script.ScriptEngine {
private static final String OUTPUT_EVENT = "event";
public static final String MIMETYPE_OPENHAB_DSL_RULE = "application/vnd.openhab.dsl.rule";
private static final Map<String, String> implicitVars = Map.of("command", "receivedCommand", "event",
"receivedEvent", "state", "newState", "newState", "newState", "oldState", "previousState", "triggeringItem",
"triggeringItem");
private static final Map<String, String> IMPLICIT_VARS = Map.of("command",
ScriptJvmModelInferrer.VAR_RECEIVED_COMMAND, "state", ScriptJvmModelInferrer.VAR_NEW_STATE, "newState",
ScriptJvmModelInferrer.VAR_NEW_STATE, "oldState", ScriptJvmModelInferrer.VAR_PREVIOUS_STATE,
"triggeringItem", ScriptJvmModelInferrer.VAR_TRIGGERING_ITEM);
private final Logger logger = LoggerFactory.getLogger(DSLScriptEngine.class);
@@ -137,12 +143,24 @@ public class DSLScriptEngine implements javax.script.ScriptEngine {
}
}
DefaultEvaluationContext evalContext = new DefaultEvaluationContext(parentContext);
for (Map.Entry<String, String> entry : implicitVars.entrySet()) {
for (Map.Entry<String, String> entry : IMPLICIT_VARS.entrySet()) {
Object value = context.getAttribute(entry.getKey());
if (value != null) {
evalContext.newValue(QualifiedName.create(entry.getValue()), value);
}
}
// now add specific implicit vars, where we have to map the right content
Object value = context.getAttribute(OUTPUT_EVENT);
if (value instanceof ChannelTriggeredEvent) {
ChannelTriggeredEvent event = (ChannelTriggeredEvent) value;
evalContext.newValue(QualifiedName.create(ScriptJvmModelInferrer.VAR_RECEIVED_EVENT), event.getEvent());
}
if (value instanceof ItemEvent) {
ItemEvent event = (ItemEvent) value;
evalContext.newValue(QualifiedName.create(ScriptJvmModelInferrer.VAR_TRIGGERING_ITEM_NAME),
event.getItemName());
}
return evalContext;
}
@@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory
import org.openhab.core.items.Item
import org.openhab.core.types.Command
import org.openhab.core.types.State
import org.openhab.core.thing.events.ChannelTriggeredEvent
import org.openhab.core.events.Event
/**
* <p>Infers a JVM model from the source model.</p>
@@ -43,6 +43,9 @@ class ScriptJvmModelInferrer extends AbstractModelInferrer {
/** Variable name for the item in a "state triggered" or "command triggered" rule */
public static final String VAR_TRIGGERING_ITEM = "triggeringItem";
/** Variable name for the item in a "state triggered" or "command triggered" rule */
public static final String VAR_TRIGGERING_ITEM_NAME = "triggeringItemName";
/** Variable name for the previous state of an item in a "changed state triggered" rule */
public static final String VAR_PREVIOUS_STATE = "previousState";
@@ -108,11 +111,13 @@ class ScriptJvmModelInferrer extends AbstractModelInferrer {
static = true
val itemTypeRef = script.newTypeRef(Item)
parameters += script.toParameter(VAR_TRIGGERING_ITEM, itemTypeRef)
val itemNameRef = script.newTypeRef(String)
parameters += script.toParameter(VAR_TRIGGERING_ITEM_NAME, itemNameRef)
val commandTypeRef = script.newTypeRef(Command)
parameters += script.toParameter(VAR_RECEIVED_COMMAND, commandTypeRef)
val stateTypeRef = script.newTypeRef(State)
parameters += script.toParameter(VAR_PREVIOUS_STATE, stateTypeRef)
val eventTypeRef = script.newTypeRef(ChannelTriggeredEvent)
val eventTypeRef = script.newTypeRef(String)
parameters += script.toParameter(VAR_RECEIVED_EVENT, eventTypeRef)
val stateTypeRef2 = script.newTypeRef(State)
parameters += script.toParameter(VAR_NEW_STATE, stateTypeRef2)
@@ -12,6 +12,7 @@
*/
package org.openhab.core.items.events;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.types.State;
/**
@@ -21,6 +22,7 @@ import org.openhab.core.types.State;
*
* @author Christoph Knauf - Initial contribution
*/
@NonNullByDefault
public class GroupItemStateChangedEvent extends ItemStateChangedEvent {
/**
@@ -12,7 +12,8 @@
*/
package org.openhab.core.items.events;
import org.openhab.core.events.AbstractEvent;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.types.Command;
/**
@@ -21,15 +22,14 @@ import org.openhab.core.types.Command;
*
* @author Stefan Bußweiler - Initial contribution
*/
public class ItemCommandEvent extends AbstractEvent {
@NonNullByDefault
public class ItemCommandEvent extends ItemEvent {
/**
* The item command event type.
*/
public static final String TYPE = ItemCommandEvent.class.getSimpleName();
private final String itemName;
private final Command command;
/**
@@ -41,9 +41,9 @@ public class ItemCommandEvent extends AbstractEvent {
* @param command the command
* @param source the source, can be null
*/
protected ItemCommandEvent(String topic, String payload, String itemName, Command command, String source) {
super(topic, payload, source);
this.itemName = itemName;
protected ItemCommandEvent(String topic, String payload, String itemName, Command command,
@Nullable String source) {
super(topic, payload, itemName, source);
this.command = command;
}
@@ -52,15 +52,6 @@ public class ItemCommandEvent extends AbstractEvent {
return TYPE;
}
/**
* Gets the item name.
*
* @return the item name
*/
public String getItemName() {
return itemName;
}
/**
* Gets the item command.
*
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2010-2020 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.core.items.events;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.events.AbstractEvent;
/**
* {@link ItemEvent} is an abstract super class for all command and state item events.
*
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public abstract class ItemEvent extends AbstractEvent {
protected final String itemName;
/**
* Constructs a new item state event.
*
* @param topic the topic
* @param payload the payload
* @param itemName the item name
* @param source the source, can be null
*/
public ItemEvent(String topic, String payload, String itemName, @Nullable String source) {
super(topic, payload, source);
this.itemName = itemName;
}
/**
* Gets the item name.
*
* @return the item name
*/
public String getItemName() {
return itemName;
}
}
@@ -77,7 +77,7 @@ public class ItemEventFactory extends AbstractEventFactory {
} else if (ItemStateEvent.TYPE.equals(eventType)) {
return createStateEvent(topic, payload, source);
} else if (ItemStatePredictedEvent.TYPE.equals(eventType)) {
return createStatePredictedEvent(topic, payload, source);
return createStatePredictedEvent(topic, payload);
} else if (ItemStateChangedEvent.TYPE.equals(eventType)) {
return createStateChangedEvent(topic, payload);
} else if (ItemAddedEvent.TYPE.equals(eventType)) {
@@ -115,7 +115,7 @@ public class ItemEventFactory extends AbstractEventFactory {
return new ItemStateEvent(topic, payload, itemName, state, source);
}
private Event createStatePredictedEvent(String topic, String payload, String source) {
private Event createStatePredictedEvent(String topic, String payload) {
String itemName = getItemName(topic);
ItemStatePredictedEventPayloadBean bean = deserializePayload(payload, ItemStatePredictedEventPayloadBean.class);
State state = getState(bean.getPredictedType(), bean.getPredictedValue());
@@ -262,7 +262,7 @@ public class ItemEventFactory extends AbstractEventFactory {
* @return the created item state event
* @throws IllegalArgumentException if itemName or state is null
*/
public static ItemStateEvent createStateEvent(String itemName, State state) {
public static ItemEvent createStateEvent(String itemName, State state) {
return createStateEvent(itemName, state, null);
}
@@ -12,7 +12,7 @@
*/
package org.openhab.core.items.events;
import org.openhab.core.events.AbstractEvent;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.types.State;
/**
@@ -22,15 +22,14 @@ import org.openhab.core.types.State;
*
* @author Dennis Nobel - Initial contribution
*/
public class ItemStateChangedEvent extends AbstractEvent {
@NonNullByDefault
public class ItemStateChangedEvent extends ItemEvent {
/**
* The item state changed event type.
*/
public static final String TYPE = ItemStateChangedEvent.class.getSimpleName();
protected final String itemName;
protected final State itemState;
protected final State oldItemState;
@@ -46,8 +45,7 @@ public class ItemStateChangedEvent extends AbstractEvent {
*/
protected ItemStateChangedEvent(String topic, String payload, String itemName, State newItemState,
State oldItemState) {
super(topic, payload, null);
this.itemName = itemName;
super(topic, payload, itemName, null);
this.itemState = newItemState;
this.oldItemState = oldItemState;
}
@@ -57,15 +55,6 @@ public class ItemStateChangedEvent extends AbstractEvent {
return TYPE;
}
/**
* Gets the item name.
*
* @return the item name
*/
public String getItemName() {
return itemName;
}
/**
* Gets the item state.
*
@@ -12,7 +12,8 @@
*/
package org.openhab.core.items.events;
import org.openhab.core.events.AbstractEvent;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.types.State;
/**
@@ -21,15 +22,14 @@ import org.openhab.core.types.State;
*
* @author Stefan Bußweiler - Initial contribution
*/
public class ItemStateEvent extends AbstractEvent {
@NonNullByDefault
public class ItemStateEvent extends ItemEvent {
/**
* The item state event type.
*/
public static final String TYPE = ItemStateEvent.class.getSimpleName();
private final String itemName;
private final State itemState;
/**
@@ -41,9 +41,8 @@ public class ItemStateEvent extends AbstractEvent {
* @param itemState the item state
* @param source the source, can be null
*/
protected ItemStateEvent(String topic, String payload, String itemName, State itemState, String source) {
super(topic, payload, source);
this.itemName = itemName;
protected ItemStateEvent(String topic, String payload, String itemName, State itemState, @Nullable String source) {
super(topic, payload, itemName, source);
this.itemState = itemState;
}
@@ -52,15 +51,6 @@ public class ItemStateEvent extends AbstractEvent {
return TYPE;
}
/**
* Gets the item name.
*
* @return the item name
*/
public String getItemName() {
return itemName;
}
/**
* Gets the item state.
*
@@ -12,7 +12,7 @@
*/
package org.openhab.core.items.events;
import org.openhab.core.events.AbstractEvent;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.types.State;
/**
@@ -26,14 +26,14 @@ import org.openhab.core.types.State;
*
* @author Simon Kaufmann - Initial contribution
*/
public class ItemStatePredictedEvent extends AbstractEvent {
@NonNullByDefault
public class ItemStatePredictedEvent extends ItemEvent {
/**
* The item state predicted event type.
*/
public static final String TYPE = ItemStatePredictedEvent.class.getSimpleName();
protected final String itemName;
protected final State predictedState;
protected final boolean isConfirmation;
@@ -48,8 +48,7 @@ public class ItemStatePredictedEvent extends AbstractEvent {
*/
public ItemStatePredictedEvent(String topic, String payload, String itemName, State predictedState,
boolean isConfirmation) {
super(topic, payload, null);
this.itemName = itemName;
super(topic, payload, itemName, null);
this.predictedState = predictedState;
this.isConfirmation = isConfirmation;
}
@@ -59,15 +58,6 @@ public class ItemStatePredictedEvent extends AbstractEvent {
return TYPE;
}
/**
* Gets the item name.
*
* @return the item name
*/
public String getItemName() {
return itemName;
}
/**
* Gets the predicted item state.
*