Refactoring code is a great way to learn though.
As @binderth indicates, it’s mostly a matter of preference. But for the sake of showing some more OH ways of managing something like this here’s one way I would do it using separate rules.
-
Create a separate rule in the UI with just a Script Action for each of your top level if conditions with the code for just that one condition.
-
I’d write my actions in JS Scripting so I can use openHAB Rules Tools Announcements (now available through openHABian) and the Gatekeeper to schedule the sequences of events. So, for example, the sonos ON and announcement OFF script would be:
var {Gatekeeper} = requires('openhab_rules_tools');
var gk = cache.get(ruleUID+'_gatekeeper', () => { new gatekeeper.Gatekeeper('kitchen motion morning'); });
items.getItem['Landing_Blind_vSwitch'].sendCommand('OFF');
items.getItem['Kitchen_Morning_Announcement'].sendCommand('ON');
gk.addCommand('PT1s', () => { items.getItem['Kitchen_Sonos_Volume'].sendCommand('15'); });
gk.addCommand('PT10s', () => { items.getItem['Announcement_Type'].sendCommand('22'); });
gk.addCommand('PT30s', () => {
items.getItem('Kitchen_Sonos_Volume').sendCommand('20');
items.getItem('Kitchen_Sonos_Tuneinstationid').sendCommand('6894');
items.getItem('Kitchen_Sonos_Control').sendCommand('PLAY');
}
gk.addCommand(0, () => { items.getItem('Announcement_Type').sendCommand('9'); });
Gatekeeper takes two arguments, the first is how long to wait after executing the second argument before running the next command. addCommand means “run this now then wait to run the next command”. The PT30s is and ISO8601 formatted duration string (this one means 30 seconds). It uses timers so it won’t monopolize the rule for seconds at a time. All the timer management stuff is handled for you so all you have to worry about is the times and the functions to run.
Then add a Script Condition to each that tests for whether it’s OK to run that rule now. You wouldn’t even need code for this and can do it all using the built in UI conditions. But if you were to write it as code it’d look something like:
time.toZDT().isBetweenTimes('6:00 AM', '9:00 AM')
&& items.getItem['Study_ZW089_vDoor'].state == 'CLOSED'
Though again, I’d probably just use the UI conditions.
- Add a trigger to each separate rule to trigger when motion is detected. But but use the appropriate trigger so those rules that should only run when it changes to ON run (e.g. in Rules DSL
Item MotionSensor changed to ON) and the one rule that should run when it changes to OFF runs when it changes to OFF. You don’t need to make that a condition if the rule only triggers when it’s appropriate.
There are advantages and disadvantages here. Adding new behaviors is as simple as adding a new rule and you don’t need to mess with what’s already working. But it breaks up the logic so you can’t just look everything on the screen a the same time.
Another advantage is that rule Conditions are likely to be easier to read and understand than complex if/else if clauses as you can add additional documentation in the UI.
But of course you could add comments to achieve the same here.
Note: all code written above is untested and almost certainly contains typos and errors. It’s more just for illustration purposes. Cargo cult programmers beware!
