Put all the lights into a Group. I’ll call it Lights
. Then
rule "Set lights to OFF"
when
System started
then
createTimer(now.plusSeconds(30), [ | Lights.sendCommand(OFF) ])
end
The Timer should help to avoid that parallel loading problem.
But the question is why must they be OFF? Why not leave them as they are and only turn some ON or OFF if an automation event was missed (e.g. the time of day changed)? If you use retained messages for the commands, then when OH comes up it will immediately know what state the lights are supposed to be in if they are online. If they are offline then the lights will become that state when they come back online.
Like I described, just use a retained message when you command the light and the light will return to that state when it comes back online (e.g. in a power outage).
There is no such thing as “querying” in MQTT. There are either unretained messages in which case the client needs to be connected to receive the message, or retained messages in which case the client will receive the last published message even if it wasn’t connected when the message was sent.
So you want them to return to the last state they were commanded to from OH. That is exactly what a retained message would do.
Again, retained messages would solve this.
See Loop of flashing light inside a timer - #2 by rlkoshak
It’s not unreasonable, you are just going about achieving it the hard way.
This really isn’t OH’s job. Use the capabilities of MQTT to your advantage.
But even if it were OH’s job, you are still going about it the hard way. Another simple approach would be:
- put all the lights into one Group, we’ll call it
Lights
- configure
Lights*
to be persisted on everyChange and restoreOnStartup - run a simple Rule at startup to sendCommand to the lights with the restored state from the database
rule "Restore lights"
when
System started
then
createTimer[now.plusSeconds(30) | Lights.members.forEach[ light | light.sendCommand(light.state) ]
end
To restore a light to it’s previously commanded state when it comes online (assuming you don’t use retained messages) you would need to get some sort of message to indicate that it has come online. You could look for the LWT message and then use the first message after that to indicate it has come back online to then sendCommand the Item’s current state in OH. Again, using Persistence the rule would look something like (using Design Pattern: Associated Items):
import org.eclipse.smarthome.model.script.ScriptServiceUtil
rule "Came back online?"
when
Item Member of Lights changed
then
val lwt = ScriptService.getItemRegistry.getItem(triggeringItem.name+"_LWT")
hist = triggeringItem.previousState(true).getTimeStamp()
if(lwt.lastUpdate.isAfter(hist)) triggeringItem.sendCommand(hist.state)
end
If the previous state of the Light that is different from the current state is before the most recent LWT message, this is the first message after the LWT so send the last state of the light back to the light.
NOTE: I just typed in these Rules, they likely contain errors.
That is something your device needs to implement and publish a message. There isn’t anything you can do from OH. MQTT doesn’t work that way.
If you have a Rule triggered with a changed
trigger, then there will be a variable called previousState
. This variable does not require Persistence.
It’s a long time bug that hasn’t been fixed.
It wouldn’t be bad but I think this entire approach to do what you are after is not the best way to achieve what you are after so I’m questioning whether it’s worth dealing with this particular problem in the first place.