rule "myrule"
when
Item item1 changed or
Item item2 changed
then
var location = triggeringItem.state.toString
var itemName = triggeringItem.name.toString
if (itemName = item1) {
....
}
....
end
I didn’t know this existed…learned something new today.
I just cut down a whole group of rules from 363 lines to 160. I could probably shave another 10 or so lines of by doing the group thing… 1 Step at a time. I should make sure this all works now that I’ve monkeyed with the whole thing!
rule "whatever"
when
Item lrF1 received command or
Item lrF2 received command or
Item lrF3 received command
then
var itemName = triggeringItem.name.toString
logInfo("triggering item: ",itemName.toString)
if ( itemName = lrF1) {
logInfo("who triggered: ","Fan 1")
if ( lrF1.state == 1 ) {
fan1.sendCommand(ON)
} else {
fan1.sendCommand(OFF)
}
}
I’ll only get the first loginfo and the name will match but then comparing itemname to the item doesn’t work. I get no second loginfo…
NOTE: Because triggeringItem.name and itemName are already a String, it is redundant to call toString on them,
rule "whatever"
when
Item lrF1 received command or
Item lrF2 received command or
Item lrF3 received command
then
val itemName = triggeringItem.name
logInfo("triggering item: " , itemName)
if(itemName == "lrF1") {
logInfo("who triggered: ","Fan 1")
fan1.sendCommand(if(receivedCommand == 1) ON else OFF)
}
else if(triggeringItem.name == "lrF2") {
...
Some further notes on what I changed:
use val instead of var for constants like itemName
don’t call toString on Strings
use quotes around “lrF1” to compare it itemName
use receivedCommand instead of lrF1.state because the Rule will be triggered before the Item get’s updated so lrF1.state is not guaranteed to equal the command that triggered the Rule
I use the trinary operator to reduce the conversion from lrF1.state to a command to fan1 down to one line.
rule "whatever"
when
Member of lrFs received commands
then
val name = triggeringItem.name
val fanName = "fan" + name.charAt(name.length() - 1)
val newState = if(receivedCommand == 1) "ON" else "OFF"
logInfo("whatever", "Sending " + newState + " to " + fanName)
sendCommand(fanName, newState)
end
That’s all there is to it. Assuming you continue to use the same naming scheme and have no more than 10 lrFs (i.e. no two digit numbers) this rule will work for all of your lrFs and fans.
In the interim (prior to your reply) I got it working with:
if ( itemName.toString == "lr24CLSw" ) {
I do a brief Thread::sleep prior to anything, the rule was just a quick stand in for the huge blob i’m actually using. I used “received command” Since the thing sending the command might not always know whether it’s sending an on or off (things get out of sync during reboots and system starts). Months ago before i understood the order in which things came that problem absolutely plagued me on some rules. Thanks for your tips, I’ll do some additional cleanup later this evening. Always appreciate your help @rlkoshak
And yeah, the groups thing is planned, too. one step at a time. If I change too much and something breaks it makes it harder for me to figure out where it got screwed up. Programming is not my specialty!
It’s a good approach. I didn’t post the above assuming you would just use it, though that is cool too. I mainly posted it to show you an end goal you can get to / work towards. It might inform your decisions on what to tackle learning when and give you some changes you can make early on that will help you later (e.g. use a naming scheme where you can construct the name of the fan Item using a part of the name for the triggering Item.
oh for sure. my naming scheme for items has changed and evolved several times since starting down this openhab path. Then Ive introduced proxies and on and on. I have quite a mix of stuff going on. It’s nice to go back and rewrite an old rule with better item names, proxies, checking to see if i actually need to send a state or not (why clutter the log?), and on and on. Another time you helped me without knowing it was mapdb for restoreonstartup. I was having terrible slowness because i was persisting a ton of stuff with rrjd4 but i had no idea it was the persistence was doing it. At some point I came across it that that was the problem and then found a thread of yours about using mapdb just for that purpose.
sorry to clog the thread up. someone may find that info useful, you just never know. They might be in here reading about triggeringitem and see the persistence slow down and say “hey, i’ve got that problem too!”
You should be able to collapse your rule down further, like this…
rule "whatever"
when
Item lrF1 received command or
Item lrF2 received command or
Item lrF3 received command
then
logInfo("triggering item: ",triggeringItem.name)
sendCommand(triggeringItem.name.replace("lfr","fan"),if (triggeringItem.state == 1) "ON" else "OFF")
end
@rlkoshak So, I’m building the rule. The switch can be actuated by 3 different sources and I need to update the other two sources when a command comes in… this part I don’t know how to do (the rest I understand, mostly).
The items would be
lr24Fan1, lr35Fan1, and lrOhFan1 (a 2.4 inch nextion, a 3.5 inch nextion, and a sitemap item).
if lr24Fan1 gets a 1 or 0 i need to sendCommand to lr35f1 and postUpdate to lrOhFan1
if lrOhFan1 gets an on or off I need to sendCommand to lr35f1 and lr24f1
the ohFan I think i got:
val ohFanName = "lrOhFan + name.charAt(name.length() - 1)
postUpdate(ohFanName, newState)
What I’m not sure about is how to decide whether to send to lr24 or lr35.
You don’t want to sendCommand because that will retrigger the rule and you will end up in an infinite loop.
If you have to sendCommand then this just got REALLY complicated because you need to somehow distinguish between a command received by pressing the button and a command received from the Rule.
We can short circuit this a bit and make it so the Role only gets called a couple of extra times, but can your fans handle getting commanded twice in very fast succession?
Basically what you will do is send your command and update to all three Items, but only if the command you are about to send us different from the current state of the Item. This will short circuit the loop.
Thanks a lot @rlkoshak.
It worked right away with no single error.
I just merged 3 rules doing the same - now just one starting with:
rule "Lookup Address for Geolocations"
when
Member of G_Locations changed
then
var itemName = triggeringItem.name.toString
var location = triggeringItem.state.toString
// get lat lon from item
val String lat = transform("REGEX", "(.*),.*", location)
val String lon = transform("REGEX", ".*,(.*)", location)
logInfo("car.rules", "lat: >" + lat + "< / lon: >" + lon + "<")
notice lr24Fan1 and lr24f1 are two different items. One is an input to openhab from the panel the other an output from openhab to the panel. lr24(35)Fan1 is the switch while lr24(35)f1 is the command sent back to the panel to update the display.
using suggestions in this topic i’ve now reduced a rule file from an original size of 363 lines to 110 and learned a great deal in the process. I’m sure this will lead to reduced execution time and, of course, greatly reduces complexity. I know I can apply this to quite a few other rules as well.
My assumption though is if you send a command to one and it changes state that results in a command sent to the other to report the change in state. If that isn’t the case then the problem may not be that big of one.
When writing like Rules like these make sure to keep an eye on how events cascade. You may be good to go. I’m glad you found the examples useful.
They’re very separate events. Definitely didn’t want things re-triggering.
Here are the rules as they stand (using @5iver’s hint):
rule "Ceiling Fans - Individual via 2.4 Nextion"
when
Member of gLrFans24 received command
then
Thread::sleep(100)
sendCommand(triggeringItem.name.replace("lr24","lr"),if (triggeringItem.state == 1) "ON" else "OFF")
postUpdate(triggeringItem.name.replace("lr24","lrOh"),if (triggeringItem.state == 1) "ON" else "OFF")
sendCommand(triggeringItem.name.replace("lr24Fan","lr35f"),if (triggeringItem.state == 1) "1" else "0")
end
rule "Ceiling Fans - Individual via 3.5 Nextion"
when
Member of gLrFans35 received command
then
Thread::sleep(100)
sendCommand(triggeringItem.name.replace("lr35","lr"),if (triggeringItem.state == 1) "ON" else "OFF")
postUpdate(triggeringItem.name.replace("lr35","lrOh"),if (triggeringItem.state == 1) "ON" else "OFF")
sendCommand(triggeringItem.name.replace("lr35Fan","lr24f"),if (triggeringItem.state == 1) "1" else "0")
end
Using his example or yours, how could I combine these two? I don’t know quite well enough how to manipulate item names inline. Also I had no idea so much could be done inline of the sendcommand/postupdate, very cool.
inputs to openhab from touchpanel
lr24Fan1(1-4)
lr35Fan1(1-4)
outputs to panel from openhab
lr24f1(1-4)
lr35f1(1-4)
OH switch for same
lrOhFan1(1-4)
Proxy to sonoff switch:
lrFan1(1-4)
I have groups already created to combine all of the fan switches (gLrFans) for when I understand how the rules can be combined.