Then I used a rule to loop through all items in the group like
when
Item galive changed to OFF
then
galive.members.forEach[ item |
if (item.name.state == "OFF") {
do something with item.name
}
]
In OH3 this does not work any more. I have the group defined having the correct group members (items), but an error occurs “[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘notifications-10’ failed: ‘state’ is not a member of ‘java.lang.String’;”
Why? I have defined galive as item and it is shown as an item in the list of items in the OH3 item interface. The error points me to the if-condition, I suppose item.name.state is wrong somehow. When I comment out everything relating to the if-condition, no error occurs.
I guarantee this never worked in any version of OH. item.name.state is essentially nonsense. item is an Item. An Item has a name which is a String that is the Item’s name (e.g. “device1”). An Item also has a state. The Item’s name doesn’t have a state. You want to use item.state.
That will address the error in the log. But you probably have a second error here. A Switch Item’s state is ON or OFF, not the strings "ON" and "OFF". So the comparison would likely always return false and do something will never run.
And of course “do something with item.name” is kind of nonsense code too. Please don’t truncate, edit, or otherwise try to make our lives easier by posting anything except the actual code, character by character, that is producing the error. If you understood the problem you wouldn’t have posted here in the first place. And by not posting the actual code that generates the error you prevent us from understanding the code that is producing the error and it ends up wasting everyone’s time.
Finally, not an error but a better way to write this would be:
galive.members.filter[ i | i.state == OFF ].forEach[ i |
// do something with each Item that is OFF
]
Hmmm, interesting. Thanks to the feedback from all of you it appears to work now:
rule "alive test"
when
Member of galive changed from ON to OFF
then
Thread::sleep(2000)
galive.members.filter[ i | i.state == OFF ].forEach[ i |
//do something
]
end
Why sleep for two seconds? In OH 2.5 that was a really bad idea. In OH 3 it’s a less bad idea (at least for now unless the rule thread pool is reintroduced) but still not a great practice. What problem are you hoping to solve with this sleep?
As written the following will happen in OH 3:
a member of galive changes from ON to OFF
the rule is triggered
the rule sleeps for two seconds
another member of galive changes from ON to OFF
the rule is locked, only one instance of it at a time can run in OH 3, so this second event waits for the rule to exit before triggering again
the two seconds are done, loop through the group and “do something”
the rule exits and then immediately triggers again, repeat the steps above.
Ok, makes sense in this case. But I don’t understand the explanation fully. There may be rules where I want to avoid that the rule is triggered twice during a certain time span. I have for example a motion sensor which provides me “1” when motion is detected. Upon motion detection I turn the light on for 5 minutes. Any additional motion should either be ignored during that time or (even better) reset the timer. If I understood you correctly, just having a Tread-Sleep would pause the rule but all the other events “1 … 1 … 1 …” will accumulate in the meantime? In other words, the rule would be resumed for the other triggers as soon as the thread wakes up again?
I somehow circumvented that issue using a creatTimer which is reset with each motion
Just walking by the sensor will create a lot lot lot of "1 1 1 1 1 1 " in a short time frame which will restart the rule every time and there will be sent hundreds of sendCommand(lightbulb, ON) in case you are dancing in front of the sensor for a few minutes.
A fairly obvious way is with if() … if it’s already state ON, don’t command it ON again. Or to put it another way,if it’s not-ON then do the ON command. That assumes you have accurate feedback from the target device.