Provide a trigger for thing Online/Offline status in rule. #3001
Conversation
We're going to expose thing status to rule. This is the first step toward the goal. The rule engine needs to subscribe to the event. Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
The syntax is "Thing <thingUid> changed [from <oldState>] [to <newState>]" Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
Similar to how ItemRegistry is exposedin RulesJvmModelInferrer, ThingRegistry is exposed in RulesJvmModelInferrer.xtend Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
RulesThingsRefresher acts like RulesItemRefresher. It listens to things changes (added/removed) and schedules to reload the rules. Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
Convert the thing status from online to Online which is used in the rule. Other thing status are converted to Offline. The rule engine also supports the rule with trigger thing state change. Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
Add the syntax 'Thing' <thingUid> 'received update' in the syntax file. This is similar to item status update. Handle the thing status event and execute thing update rule in rule engine. Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
The rule is changed to take thingUid as a string instead of an ID. And we don't use the type Thing internally to pass the information in the rule. This is done so because when the thing is removed, it can occur before the rule is checked and executed. When it occurs, we cannot get the Thing from thingUid. Fix an issue in storing thing related rules and retrieve them. Bug: eclipse-archived#1654 Signed-off-by: Maoliang Huang <hellomao@outlook.com>
After I spent a few hours fixing the failing test (https://travis-ci.org/eclipse/smarthome/builds/200974384), I have to ask for help. Running org.eclipse.smarthome.model.script.tests.scriptengine.ScriptEngineOSGiTest testInterpreter(org.eclipse.smarthome.model.script.tests.scriptengine.ScriptEngineOSGiTest) Time elapsed: 0.465 sec <<< FAILURE!
In the test, it verifies the ScriptServiceUtil is not null but it is
The only change in ScriptServiceUtil is
My guess is that ThingRegistry isn't created some how. I tried to debug like
or
or
All of them return zero. I am not quite familiar internal OSGI works. During my debugging, what I can tell is that those classes (ThingRegistry, ThingHandlerFactory, ThingHandler) are found (somewhere LoadClass is called and it is successful). But an instance isn't created (don't have this source code and don't understand what's going on). Thus it returns null. Can anybody please shed a light on it? |
I'm no expert on this myself, but I assume that you are simply missing the bundle org.eclipse.smarthome.core.thing during your test executions, since this provides the ThingRegistry as a service. Note that you can add additional required dependencies here, which are then available during the test execution. Check also https://www.eclipse.org/smarthome/documentation/development/testing.html#groovy. |
- Need to add the bundle org.eclipse.smarthome.thing to the plugin in pom.xml. Signed-off-by: Maoliang Huang <hellomao@outlook.com>
Thanks @kaikreuzer . That works. I added it to pom.xml and updated the pull request. |
Cool, seems that you are making progress. When will this feature be available in the snapshot relaease? |
I don't see any reviews yet and the maintainers don't approve it yet. I think that is the process to complete the pull request. Until then, I don't think it'll be in snapshot release soon. |
Thanks for the info @kceiw. I can hardly wait to use this feature :-) |
You are right 😉 |
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.
Sorry, I also didn't yet find the time for a thorough review and test.
I think @kceiw did a tremendous job and really dived deep into the whole Xtext inner workings - definitely no easy job, congrats!
I just did a cursory review and have some initial remarks - the main one being a misconception about Item State vs. Thing Status.
import org.eclipse.smarthome.core.types.PrimitiveType; | ||
import org.eclipse.smarthome.core.types.State; | ||
|
||
public enum OnlineOfflineType implements PrimitiveType, State, Convertible { |
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.
ONLINE/OFFLINE must not be introduced as a new state - it is a "status" which only applies for Things, not for Items.
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.
Please see the comment in Rules.xtext about ValidState and ThingStatusInfo
@@ -28,6 +28,7 @@ Import-Package: org.eclipse.smarthome.core.common.registry, | |||
org.quartz.spi, | |||
org.quartz.utils, | |||
org.slf4j | |||
Require-Bundle: org.eclipse.smarthome.model.rule | |||
Require-Bundle: org.eclipse.smarthome.model.rule, | |||
org.eclipse.smarthome.core |
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.
please use Import-Package instead
@@ -72,6 +74,13 @@ SystemOnShutdownTrigger: | |||
'System' 'shuts down' | |||
; | |||
|
|||
ThingStateUpdateEventTrigger: | |||
'Thing' thing=STRING 'received update' (state=ValidState)? |
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.
The update is not a "ValidState", but ThingStatus (or even rather a ThingStatusInfo, check out the classes - it would need to be decided what syntax to use here in the DSL for it).
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.
How about exposing ThingStatusInfo to the rule and scripts.
How about this new syntax?
'Thing' thing=STRING 'received update' (state=ThingStatusInfo)?
ThingStatusInfo = STRING // or something that make sense and can be converted from ThingStatusInfo
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.
Instead of allowing strings (and requiring hyphens around them), I think we should better introduce dedicated keywords - it is a well defined list, so this should not be hard.
Not sure if we would also have to make the ThingStatusDetail available here, which would complicate stuff - I'd therefore suggest to leave it out of scope and rather only make the ThingStatusInfo available within the "then" block, so that more detailed constraints can be implemented in there.
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.
That sounds good to me. So we agree on the syntax like "Thing thing=STRING received update (state=ThingStatusInfo)" And "ThingStatusInfo=... (the well defined list)"
- Use a pre-defined list as the thing status. the list is the same as ThingStatus. Bug: eclipse-archived#1654 Signed-off-by: kceiw <hellomao@outlook.com>
- The thing uid contains ':' which cannot be used as an identifier. So we cannot use something like "ThingType:Thing" in the script and interpreset it as a thing. So we need to create an action to accept the thing uid and return its status. - This is to allow the user to create more restrains using ThingStatusInfo in the script. Bug: eclipse-archived#1654 Signed-off-by: kceiw <hellomao@outlook.com>
Bug: eclipse-archived#1654 Signed-off-by: kceiw <hellomao@outlook.com>
Hi @kaikreuzer At the same time, I create a new action (ThingAction) for script. The user can use this action to get ThingStatusInfo in 'then' block. I cannot use dot notation like "item.state" because a thing uid contains ':' which make it an invalid identifier in the script. So I create the action to accept the thing uid and return ThingStatusInfo. Can you look at that again and give me more feedback? |
Bug: eclipse-archived#1654 Signed-off-by: kceiw <hellomao@outlook.com>
I tested with a rule. Verify that the rule is executed when the updated/changed events are fired. And getThingStatusInfo() returns the right ThingStatusInfo in 'then' script. |
Many thanks @kceiw, this sounds good and at a quick glance, the code looks very clean as well - incredible, how you dived into Xtext/Xbase/actions etc. 👍 |
result = Iterables.concat(thingUpdateEventTriggeredRules.values()); | ||
break; | ||
case THINGCHANGE: | ||
result = Iterables.concat(thingChangedEventTriggeredRules.values()); |
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.
case THINGUPDATE: | ||
for (Set<Rule> rules : thingUpdateEventTriggeredRules.values()) { | ||
rules.remove(rule); | ||
} |
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.
missing break
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'll create a new PR.
@kceiw As this PR has already been merged, can you create a new one that adds a break / return in every case branch? |
Hi, This looks like what I need, thank you for your work on this. Thank you, |
@yo8192 Thanks. You can find from Paper UI. It's a string separate by ':' In your rule or script, you can get the thing state by using |
@kceiw You are right that the ESH documentation does not cover such features at all. |
This pull request has been mentioned on openHAB Community. There might be relevant details there: https://community.openhab.org/t/how-to-restart-binding-with-in-rules/29843/8 |
The change of the code is at eclipse-archived/smarthome#3001 After this commit, the end user can find the documentation about how to react to thing status change in the rule. Bug: openhab#517 Signed-off-by: Maoliang Huang <hellomao@outlook.com> Incorporate more pull request feedback.
The change of the code is at eclipse-archived/smarthome#3001 After this commit, the end user can find the documentation about how to react to thing status change in the rule. Bug: #517 Incorporate more pull request feedback. Signed-off-by: Maoliang Huang <hellomao@outlook.com>
This is to fix the issue in #1654
With this change, the user can specify the triggers such as
"Thing received update" or "Thing changed" in a rule.
Please note that is a string instead of a ID. This is done so because thingUID contains the character ":". And Online is defined as Thing.getStatus() == ThingStatus.Online. Otherwise, it's offline. I've tested it with two simple rules that just output a log for "received update" and "changed" triggers.
This change is not try to expose thing status to script. That should be done separately.