None of what I described above assumes they are on the same device. In fact I am assuming that the broker and OH are separate because they can both be restarted independently.
Let’s say that your broker goes down but OH does not. Then your sensor changes state while the broker is down.
- The sensor will be unable to publish that state because the broker is down.
- The sensor should therefore keep trying to publish that state (or the latest state) until the broker comes back up. Or, alternatively, the sensor will wait until the broker connection is restored and immediately publishes it’s current state.
- When the broker comes back up, it will restore the retained messages and, depending on the retry rate very shortly thereafter get the sensor’s current state as a retained message.
This is all independent of OH. From the OH side of things, assuming the MQTT 2 binding the following will happen.
- OH will lose the connection to the broker and mark the broker Thing and all the Things using that broker Thing as Offline.
- All Items linked to those channels will be set to UNDEF.
- When the broker comes back online OH will get any retained messages and immediately update the Items with the retained messages on any topics that have a retained message.
- Because the sensor readings are retained messages, OH doesn’t have to be online to get the most recently published sensor reading. There might be a small race condition where OH connects before the sensor connects to the broker in which case OH will first get the old sensor reading and then after at most a few seconds it will get the most recent sensor reading when the sensor comes back online.
As someone who has implemented a “query the sensors for the most recent value” to solve exactly this same problem before, I can tell you, it is far more reliable, far more robust, and a much better and standard use of MQTT to use retained messages like I describe than to have OH send out a message to poll for the latest states.
Use the tools built into the technologies you are using to their best effect and you will have a better system over all.
Now what happens if OH goes offline but the broker stays online? In that case when OH comes back up:
- The MQTT binding will connect to the broker.
- It will receive any retained messages from any topics it subscribes to.
So there is no need to query for the current state from the sensors. The sensors have already published their most recent state to the broker and the broker retained that message. So even if OH was offline when the message was received, it will get that sensor reading as soon as it comes back online.
NOTE: Retained messages should not be used for command topics, only sensor and status topics.
While we are on the topic of retained messages, another good use for them is in the LWT topic. Configure your device to publish ONLINE as a retained message to the LWT topic when it comes online. The configure the LWT to publish OFFLINE as a retained message to the LWT topic when the broker detects that the device is offline. This way the LWT topic will always reflect the online/offline status of the device meaning that everyone who cares about it’s status (e.g. openHAB) doesn’t have to be online when the LWT message was published to know the device’s state.
This is one of those cases where a sleep is probably better. But I’m not 100% certain that this will work either. The problem is I don’t know if the context of the Rule get’s updated while the Rule is running. So if the Rule starts running before stuff has come up to the point where the publishMQTT is known before the sleep, I wouldn’t expect that it will exist after the sleep either, no matter how long the sleep is. But it might work in this case since we are going through an Action to get access to the publishMQTT action so the context may not matter that much.
What you would need to do is probably create a Timer that sends a command to an Item that kicks off another Rule after the timeout instead of trying to do it all within the System started Rule. It would probably be safest to use the Expire binding for the Timer in this case.