@rlkoshak took all your suggestions form post #11 and incorporated them. This time I edited the wiki as discussed.
It did not make sense to me to add this to the Number item section, as it is stated there:
Which would make it confusing to me, how we end up with a hex-value. Thus, I added it to the string section, please check whether you are OK with it and whether I captured it correctly.
Finally, if we are all OK, I am not sure how to proceed as it may cause conflicts with PR#469. Both should go into the rules documentation and #469 should come before this one here. I guess I will wait until #469 is merged and open another PR for issue #472 only after it merged.
The conversion is to go from hex to DecimalType, or at least. The article, in my mind at least, should cover conversions in both directions. We show both directions in the DateTime section.
It comes up frequently. All that being said, the String section is as good a place to put it as the Number section. We should probably include an example of parsing a Date Time String.
I’m on my phone for the next few days so can’t easily look up the the issue numbers. But I have no problems with what you say.
Hey guys, short reply from me. I’m currently on a surprise vacation (invited on Thursday, flight Friday morning). I think we should try to make the article a bit more systematic, as already mentioned here. Definitely something I can work on in the next couple of day (I have my laptop with me).
No, from a programming perspective that doesn’t make any sense. We could add a statement that one cannot do this but if we start going down the path of listing everything that one cannot do the article becomes infinite in length.
Having said that, if you do a little but of setup up front you can get the Item or if a group by name. See Design Pattern: Associated Items
Thanks, fair enough. I just thought about something like FAQ where “NO” would be said to questions of dummies, even if they do not make sense from a programming perspective.
I don’t know if this is relevant, but I’m trying do define a Map, like this:
var Map<GenericItem, State> LightStates = null
However this does not work, as “State cannot be resolved to a Type” Is State a Type?
If I leave the parameters off, I get a warning “Map is raw type it should be parameterized”, but it works.
I don’t know this definitively, but I do not think that one can use Java Interfaces as Types in the Rules DSL. This is also why you can’t do Map<Item, Boolean>. Since State is an Interface rather than a proper class I think you can’t define the Map like that.
casting and type coversion is something that drives me crazy as well. Maybe you can point me to the right direction:
This is the rule that should tell me when the washinmachine is done. Took the biggest part of that from annother post (I guess it was from Thom Dietrich)
val Number Waschmaschine_MODE_OFF = 0
val Number Waschmaschine_MODE_STANDBY = 1
val Number Waschmaschine_MODE_ACTIVE = 2
val Number Waschmaschine_MODE_FINISHED = 3
val Number Waschmaschine_MODE_CREASE_PROTECTION = 4
var Number Waschmaschine_Counter = 0
rule "Waschmaschine Status"
when
Item Steckdose_Waschmaschine_Strom changed
then
if (Steckdose_Waschmaschine_Strom.state < 1) Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_OFF)
else if (Steckdose_Waschmaschine_Strom.state > 100 && Waschmaschine_OpState.state !== (Waschmaschine_MODE_CREASE_PROTECTION) || Steckdose_Waschmaschine_Strom.state > 500){
Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_ACTIVE)
}
if (Waschmaschine_OpState.state == (Waschmaschine_MODE_ACTIVE) && Steckdose_Waschmaschine_Strom.state < 2){
Waschmaschine_Counter = Waschmaschine_Counter + 1
}
if (Steckdose_Waschmaschine_Strom.state > 1 && Steckdose_Waschmaschine_Strom.averageSince(now.minusMinutes(2)) < 2) {
if (Waschmaschine_OpState.state == Waschmaschine_MODE_OFF) Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_STANDBY)
}
if (Waschmaschine_Counter > 6){
if (Waschmaschine_OpState.state == Waschmaschine_MODE_ACTIVE){
Waschmaschine_Counter = 0
Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_CREASE_PROTECTION)
}
}
if (Steckdose_Waschmaschine_Strom.averageSince(now.minusMinutes(30)) < 150){
if (Waschmaschine_OpState.state == (Waschmaschine_MODE_CREASE_PROTECTION)) Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_FINISHED)
}
end
Now when loading into VSC, it throws an error like this
file: 'file:///Volumes/openHAB-share/openhab2-conf/rules/washing_machine_state.rules'
severity: 'Fehler'
message: 'Ambiguous binary operation.
The operator declarations
operator_lessThan(Number, Number) in NumberExtensions and
operator_lessThan(Type, Number) in NumberExtensions
both match.'
at: '25,114'
source: ''
code: 'org.eclipse.xtext.xbase.validation.IssueCodes.ambiguous_feature_call'
The script runs and alternates between states “0” and “2”, but never actually reaches “1”, “3” or “4”.
So I have tried “xxx as Decimal”, “(xxx as Decimal).floatValue”, replaced the figure “2” with a variable of type int or type float or type number, nothing worked. What am I doing wrong?
I think the problem is the first line of the Rule.
if (Steckdose_Waschmaschine_Strom.state < 1) Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_OFF)
Steckdose_Waschmaschine_Strom.state (assuming it is a Number Item) carries a DecimalType. But DecimalType is both of type Number and of type Type. So when the Rules Engine tries to run the < operator it doesn’t know which one to run, the one that takes Number, Number or it takes Type, Number.
You can fix this by telling the Rules Engine which < operation to call by casting the state to Number.
if (Steckdose_Waschmaschine_Strom.state as Number < 1) Waschmaschine_OpState.postUpdate(Waschmaschine_MODE_OFF)
The line you have posted is working and not mentioned by VSC. I guess the problem is exactly what you said, but I guess i’d rather need to specify the type of this expression: ‘Steckdose_Waschmaschine_Strom.averageSince(now.minusMinutes(2)’, as the comparison to ‘>2’ fails.
…and this is where I have no clue, how to do it…
Secondly, log out the result of the call from averageSince. If there is a problem with persistence or the data in the database then averageSince will return null and you can’t compare null with >.
Anytime you have errors or a rule doesn’t execute as expected:
watch the openhab.log for errors
watch events.log to verify the events that should trigger the Rule are happening
Ok, guess this I will have to check, thanks! But as the error is already stated by the editor (VSC), I’d say we should stick with the casting problem.
no errors, ‘2018-03-15 17:53:35.324 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model ‘washing_machine_state.rules’’
No additional line (error) after that. So should be fine.
The triggers are occuring (changes in current drawn by the machine. I can see it changing in the GUI, it is logged in persistence so I can draw a chart and the values are written in events.log. The rule itself works but never enters the states I have stated above. When editing the code in VSC, it returns the lines in question with the errors I have posted. Still, the rule itself runs and returns the states “off” and “active” when the specified conditions (current drawn by the machine) are true.
What else could I log? I guess you where spot on with your first reply, it must be a casting problem. So how do I cast this expression so the rule engine understands it as a number it can compare to the value of “< 2”
If you log out the result you will immediately be able to see what it is that averageSince is returning. We won’t know what we can cast it to or what we need to convert it from until we know what it is.