This repository has been archived by the owner on May 7, 2020. It is now read-only.
Provide a trigger for thing Online/Offline status in rule. #3001
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
2b3036e
RunEngineImple subscribes to ThingStatusInfoChangedEvent.
kceiw 0e6ccfe
Add a thing syntax in rule.
kceiw 9d184d0
Expose ThingRegistry in rule.
kceiw 330bea9
Refactor and add RulesThingRefresher.
kceiw 3b21b2c
Infer whether an event trigger is ThingStateChangedEventTrigger.
kceiw 12908bf
RuleEngine listens to ThingStatusChangedEvent and execut the rule.
kceiw d99a8da
Support to handle thing state update in rule engine.
kceiw f9614b7
Fix issues in thing update/change rules.
kceiw 48b3d50
Fix a test org.eclipse.smarthome.model.script.tests.
kceiw 40158b6
Merge branch 'master' into ThingStateRule
kceiw 1a55639
Change thing changed event syntax.
kceiw db3e23d
Expose ThingStatusInfo via an action.
kceiw 5eeb0e2
remove org.eclipse.smarthome.core from required package.
kceiw 25b04e9
Add missing activate functions in ThingActionService.
kceiw File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ | |
|
||
import org.eclipse.emf.ecore.util.EcoreUtil; | ||
import org.eclipse.smarthome.core.items.Item; | ||
import org.eclipse.smarthome.core.thing.ThingStatus; | ||
import org.eclipse.smarthome.core.types.Command; | ||
import org.eclipse.smarthome.core.types.State; | ||
import org.eclipse.smarthome.core.types.Type; | ||
|
@@ -34,6 +35,8 @@ | |
import org.eclipse.smarthome.model.rule.rules.RuleModel; | ||
import org.eclipse.smarthome.model.rule.rules.SystemOnShutdownTrigger; | ||
import org.eclipse.smarthome.model.rule.rules.SystemOnStartupTrigger; | ||
import org.eclipse.smarthome.model.rule.rules.ThingStateChangedEventTrigger; | ||
import org.eclipse.smarthome.model.rule.rules.ThingStateUpdateEventTrigger; | ||
import org.eclipse.smarthome.model.rule.rules.TimerTrigger; | ||
import org.eclipse.smarthome.model.rule.rules.UpdateEventTrigger; | ||
import org.quartz.CronScheduleBuilder; | ||
|
@@ -74,13 +77,17 @@ public enum TriggerTypes { | |
TRIGGER, // fires whenever a trigger is emitted on a channel | ||
STARTUP, // fires when the rule engine bundle starts and once as soon as all required items are available | ||
SHUTDOWN, // fires when the rule engine bundle is stopped | ||
TIMER // fires at a given time | ||
TIMER, // fires at a given time | ||
THINGUPDATE, // fires whenever the thing state is updated. | ||
THINGCHANGE, // fires if the thing state is changed by the update | ||
} | ||
|
||
// lookup maps for different triggering conditions | ||
private Map<String, Set<Rule>> updateEventTriggeredRules = Maps.newHashMap(); | ||
private Map<String, Set<Rule>> changedEventTriggeredRules = Maps.newHashMap(); | ||
private Map<String, Set<Rule>> commandEventTriggeredRules = Maps.newHashMap(); | ||
private Map<String, Set<Rule>> thingUpdateEventTriggeredRules = Maps.newHashMap(); | ||
private Map<String, Set<Rule>> thingChangedEventTriggeredRules = Maps.newHashMap(); | ||
// Maps from channelName -> Rules | ||
private Map<String, Set<Rule>> triggerEventTriggeredRules = Maps.newHashMap(); | ||
private Set<Rule> systemStartupTriggeredRules = new CopyOnWriteArraySet<>(); | ||
|
@@ -133,6 +140,11 @@ public Iterable<Rule> getRules(TriggerTypes type) { | |
case TRIGGER: | ||
result = Iterables.concat(triggerEventTriggeredRules.values()); | ||
break; | ||
case THINGUPDATE: | ||
result = Iterables.concat(thingUpdateEventTriggeredRules.values()); | ||
break; | ||
case THINGCHANGE: | ||
result = Iterables.concat(thingChangedEventTriggeredRules.values()); | ||
default: | ||
result = Sets.newHashSet(); | ||
} | ||
|
@@ -221,18 +233,31 @@ public Iterable<Rule> getRules(TriggerTypes triggerType, String channel, String | |
return result; | ||
} | ||
|
||
private Iterable<Rule> getAllRules(TriggerTypes type, String itemName) { | ||
public Iterable<Rule> getRules(TriggerTypes triggerType, String thingUid, ThingStatus state) { | ||
return internalGetThingRules(triggerType, thingUid, null, state); | ||
} | ||
|
||
public Iterable<Rule> getRules(TriggerTypes triggerType, String thingUid, ThingStatus oldState, | ||
ThingStatus newState) { | ||
return internalGetThingRules(triggerType, thingUid, oldState, newState); | ||
} | ||
|
||
private Iterable<Rule> getAllRules(TriggerTypes type, String name) { | ||
switch (type) { | ||
case STARTUP: | ||
return systemStartupTriggeredRules; | ||
case SHUTDOWN: | ||
return systemShutdownTriggeredRules; | ||
case UPDATE: | ||
return updateEventTriggeredRules.get(itemName); | ||
return updateEventTriggeredRules.get(name); | ||
case CHANGE: | ||
return changedEventTriggeredRules.get(itemName); | ||
return changedEventTriggeredRules.get(name); | ||
case COMMAND: | ||
return commandEventTriggeredRules.get(itemName); | ||
return commandEventTriggeredRules.get(name); | ||
case THINGUPDATE: | ||
return thingUpdateEventTriggeredRules.get(name); | ||
case THINGCHANGE: | ||
return thingChangedEventTriggeredRules.get(name); | ||
default: | ||
return Sets.newHashSet(); | ||
} | ||
|
@@ -331,6 +356,67 @@ private Iterable<Rule> internalGetRules(TriggerTypes triggerType, Item item, Typ | |
return result; | ||
} | ||
|
||
private Iterable<Rule> internalGetThingRules(TriggerTypes triggerType, String thingUid, ThingStatus oldStatus, | ||
ThingStatus newStatus) { | ||
List<Rule> result = Lists.newArrayList(); | ||
Iterable<Rule> rules = getAllRules(triggerType, thingUid); | ||
if (rules == null) { | ||
rules = Lists.newArrayList(); | ||
} | ||
|
||
switch (triggerType) { | ||
case THINGUPDATE: | ||
for (Rule rule : rules) { | ||
for (EventTrigger t : rule.getEventtrigger()) { | ||
if (t instanceof ThingStateUpdateEventTrigger) { | ||
ThingStateUpdateEventTrigger tt = (ThingStateUpdateEventTrigger) t; | ||
if (tt.getThing().equals(thingUid)) { | ||
String stateString = tt.getState(); | ||
if (stateString != null) { | ||
ThingStatus triggerState = ThingStatus.valueOf(stateString); | ||
if (!newStatus.equals(triggerState)) { | ||
continue; | ||
} | ||
} | ||
result.add(rule); | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
case THINGCHANGE: | ||
for (Rule rule : rules) { | ||
for (EventTrigger t : rule.getEventtrigger()) { | ||
if (t instanceof ThingStateChangedEventTrigger) { | ||
ThingStateChangedEventTrigger ct = (ThingStateChangedEventTrigger) t; | ||
if (ct.getThing().equals(thingUid)) { | ||
String oldStatusString = ct.getOldState(); | ||
if (oldStatusString != null) { | ||
ThingStatus triggerOldState = ThingStatus.valueOf(oldStatusString); | ||
if (!oldStatus.equals(triggerOldState)) { | ||
continue; | ||
} | ||
} | ||
|
||
String newStatusString = ct.getNewState(); | ||
if (newStatusString != null) { | ||
ThingStatus triggerNewState = ThingStatus.valueOf(newStatusString); | ||
if (!newStatus.equals(triggerNewState)) { | ||
continue; | ||
} | ||
} | ||
result.add(rule); | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* Removes all rules with a given trigger type from the mapping tables. | ||
* | ||
|
@@ -362,6 +448,12 @@ public void clear(TriggerTypes type) { | |
} | ||
timerEventTriggeredRules.clear(); | ||
break; | ||
case THINGUPDATE: | ||
thingUpdateEventTriggeredRules.clear(); | ||
break; | ||
case THINGCHANGE: | ||
thingChangedEventTriggeredRules.clear(); | ||
break; | ||
} | ||
} | ||
|
||
|
@@ -376,6 +468,8 @@ public void clearAll() { | |
clear(COMMAND); | ||
clear(TIMER); | ||
clear(TRIGGER); | ||
clear(THINGUPDATE); | ||
clear(THINGCHANGE); | ||
} | ||
|
||
/** | ||
|
@@ -430,6 +524,22 @@ public synchronized void addRule(Rule rule) { | |
triggerEventTriggeredRules.put(eeTrigger.getChannel(), rules); | ||
} | ||
rules.add(rule); | ||
} else if (t instanceof ThingStateUpdateEventTrigger) { | ||
ThingStateUpdateEventTrigger tsuTrigger = (ThingStateUpdateEventTrigger) t; | ||
Set<Rule> rules = thingUpdateEventTriggeredRules.get(tsuTrigger); | ||
if (rules == null) { | ||
rules = new HashSet<Rule>(); | ||
thingUpdateEventTriggeredRules.put(tsuTrigger.getThing(), rules); | ||
} | ||
rules.add(rule); | ||
} else if (t instanceof ThingStateChangedEventTrigger) { | ||
ThingStateChangedEventTrigger tscTrigger = (ThingStateChangedEventTrigger) t; | ||
Set<Rule> rules = thingChangedEventTriggeredRules.get(tscTrigger.getThing()); | ||
if (rules == null) { | ||
rules = new HashSet<Rule>(); | ||
thingChangedEventTriggeredRules.put(tscTrigger.getThing(), rules); | ||
} | ||
rules.add(rule); | ||
} | ||
} | ||
} | ||
|
@@ -470,6 +580,15 @@ public void removeRule(TriggerTypes type, Rule rule) { | |
timerEventTriggeredRules.remove(rule); | ||
removeTimerRule(rule); | ||
break; | ||
case THINGUPDATE: | ||
for (Set<Rule> rules : thingUpdateEventTriggeredRules.values()) { | ||
rules.remove(rule); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing break There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll create a new PR. |
||
case THINGCHANGE: | ||
for (Set<Rule> rules : thingChangedEventTriggeredRules.values()) { | ||
rules.remove(rule); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
|
@@ -497,6 +616,8 @@ public void removeRuleModel(RuleModel ruleModel) { | |
removeRules(STARTUP, Collections.singletonList(systemStartupTriggeredRules), ruleModel); | ||
removeRules(SHUTDOWN, Collections.singletonList(systemShutdownTriggeredRules), ruleModel); | ||
removeRules(TIMER, Collections.singletonList(timerEventTriggeredRules), ruleModel); | ||
removeRules(THINGUPDATE, thingUpdateEventTriggeredRules.values(), ruleModel); | ||
removeRules(THINGCHANGE, thingChangedEventTriggeredRules.values(), ruleModel); | ||
} | ||
|
||
private void removeRules(TriggerTypes type, Collection<? extends Collection<Rule>> ruleSets, RuleModel model) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
bundles/model/org.eclipse.smarthome.model.rule/OSGI-INF/rulesthingrefresher.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
|
||
Copyright (c) 2014-2016 by the respective copyright holders. | ||
All rights reserved. This program and the accompanying materials | ||
are made available under the terms of the Eclipse Public License v1.0 | ||
which accompanies this distribution, and is available at | ||
http://www.eclipse.org/legal/epl-v10.html | ||
|
||
--> | ||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.smarthome.model.rule.jvmmodel.rulesthingrefresher"> | ||
<implementation class="org.eclipse.smarthome.model.rule.jvmmodel.RulesThingRefresher"/> | ||
<reference bind="setModelRepository" cardinality="1..1" interface="org.eclipse.smarthome.model.core.ModelRepository" name="ModelRepository" policy="dynamic" unbind="unsetModelRepository"/> | ||
<reference bind="setThingRegistry" cardinality="0..1" interface="org.eclipse.smarthome.core.thing.ThingRegistry" name="ThingRegistry" policy="dynamic" unbind="unsetThingRegistry"/> | ||
<reference bind="addActionService" cardinality="0..n" interface="org.eclipse.smarthome.model.script.engine.action.ActionService" name="ActionService" policy="dynamic" unbind="removeActionService"/> | ||
</scr:component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume a break is missing here!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many thanks. I'll create a new PR.