MQTT Persistence help guide

Hello,
I use Openhab 2.4 and MQTT. I need my lights to return to their original state if openhab restarts.
Can anyone help me configure Persistence for these lights?
Thank you
.items:

Group All


Group:Switch:OR(ON, OFF) 		Fence 		    "Outside Lights   [(%d)]" 		        (All)
Number                          myHours         "my hours [%d]" 


Switch 			LightD27		 	"Fence1"	     	(Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD27/cmd:command:*:default],<[mosquitto:ST/LD27/state:state:default:.*]", autoupdate="false"}
Switch 			LightD23		 	"Fence2"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD23/cmd:command:*:default],<[mosquitto:ST/LD23/state:state:default:.*]", autoupdate="false"}
Switch 			LightD19		 	"Fence3"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD19/cmd:command:*:default],<[mosquitto:ST/LD19/state:state:default:.*]", autoupdate="false"}
Switch 			LightD18		 	"Fence4"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD18/cmd:command:*:default],<[mosquitto:ST/LD18/state:state:default:.*]", autoupdate="false"}
Switch 			LightD16		 	"Fence5"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD16/cmd:command:*:default],<[mosquitto:ST/LD16/state:state:default:.*]", autoupdate="false"}
Switch 			LightD14		 	"Fence6"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD14/cmd:command:*:default],<[mosquitto:ST/LD14/state:state:default:.*]", autoupdate="false"}
Switch 			LightD3		 	    "Fence7"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD3/cmd:command:*:default],<[mosquitto:ST/LD3/state:state:default:.*]", autoupdate="false"}
Switch 			LightD11		 	"Fence8"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD11/cmd:command:*:default],<[mosquitto:ST/LD11/state:state:default:.*]", autoupdate="false"}
Switch 			LightD24		 	"Fence9"		    (Fence, CmdGroup ) 		["Lighting"] 	{mqtt=">[mosquitto:ST/LD24/cmd:command:*:default],<[mosquitto:ST/LD24/state:state:default:.*]", autoupdate="false"}



.sitemaps:

sitemap home label="MyHome"
{

    
	Frame label=""{
		Group item=Fence {
			
		Switch item=Fence label="  [%d]" mappings=[OFF="All Off", ON="All On"] icon="switch"
        Setpoint item=myHours step=5 minValue=5 maxValue=120 icon="time"
		 
		         Switch item=LightD27
		         Switch item=LightD23		 
                 Switch item=LightD19		 	
                 Switch item=LightD18		 	
                 Switch item=LightD16		 	
                 Switch item=LightD14		 	
                 Switch item=LightD3		 	
	             Switch item=LightD11		 	
                 Switch item=LightD24	
		}
	}
	
}	

.rules:

var Timer myTimer = null

rule "my auto off rule"
when
    Item Fence changed
then
    if (Fence.state==OFF) {
        myTimer?.cancel
        myTimer = null
    }
    else if (Fence.state==ON) {
        if (myTimer!=null) {
            myTimer.cancel
            myTimer = null
        }
        myTimer = createTimer(now.plusMinutes((myHours.state as DecimalType).intValue)) [| 
           Fence.sendCommand(OFF)
        ]
    }
end        

The proper way to do this is to use retained messages. When the retained message flag is set for an MQTT message, the MQTT broker will save that message (the most recent message anyway) and when any MQTT client connects and subscribes to that topic, it will get that message automatically.

This is great for devices like lights where the command you send represents the state you want the device to be in. Do not use this for devices that get triggered (e.g. a button push) because they will get triggered again when the device reconnects.

If the command and state topics are different though, there might need to be a simple Rule to pass any manual changes to the light to the command topic as a retained message.

rule "Update retained message"
when
    Member of MQTT_Lights changed
then
    triggeringItem.sendCommand(triggeringItem.state)
end

The device will already be in this state so the command won’t really do anything except update the retained message so the device will return to it’s prior state if it goes offline and comes back online.

NOTE, for MQTT 1 you will have to create multiple broker configurations, one without the retained flag checked and one with the retained flag checked. With the MQTT 2 binding you can set the flag on a topic by topic basis.

First I have to say, that you have two Items with the same name and this won’t work(Group item and switch item). You can have equal Label-Names but not item names. But I think you can use a Group Item (items-File) as a Switch Item (sitemap).

To use a persistence you need:

  1. Install a peristence Service via Paper UI e.g. MapDB
  2. create a .persist File in the openhab-conf/persist -Folder like this
Strategies {
  default = everyChange
}
Items {
  Fence*                : strategy = everyChange, restoreOnStartup
}
  1. Set it in the Paper UI as default Persintence Service
    grafik
    That’s it.
    But under normal circumstances the state should return to OH after a restart for channel-linked items.

EDIT:
Just saw that Rich shows you the right way

Hello,
Thanks for your help.
As I said at the beginning I use OpenHab 2.4 and Mqtt.
I didn’t install MQTT Binding v2.4 - I have no idea why it doesn’t work with my external devices.
I use MQTT Action and MQTT Binding v 1.x

  1. I installed MapDB Persistance
  2. I created the “demo.persist” file in the openhab-conf / persistence folder

demo.persist:

Strategies {
  default = everyChange
}
Items {
  Fence*                : strategy = everyChange, restoreOnStartup
}
  1. I set “mapdb” in the Paper UI as default Persintence Service

It still doesn’t work - when I disconnect the power supply and connect it again my MQTT devices stay OFF
This is my hardware config :

Did you take any action when upgrading to OH 2.4? If not then your MQTT 1.x got replaced with MQTT 2.4 automatically if you have “Show legacy 1.x bindings” turned off in the settings.

But that is irrelevant to my answer. I explained how to enable retained messages for both versions.

You should be sending the command messages to your Arduino as a retained message. That’s all it takes. That’s all you have to do.

If you would rather do it the really hard and complicated way you can create a system started Rule that runs when OH comes back online with a line along the lines of

MyDevice.sendCommand(MyDevice.state)

But then you have the problem that the System started Rule may start running before MyDevice was restored from the database. And what happens if the Broker isn’t up yet when this new message is sent? What happens if the Arduino isn’t up when this new message is sent? Now you have to add all sorts of delays and checking, some of which will require modifications to the Arduino and Rules that watch the OH logs and more.

It’s a HUGE mess.

Or you can edit mqtt.cfg with another broker that is identical to your existing mosquitto broker but with a new name and with “retain=true” (maybe retained=true, I don’t remember) and change all your > MQTT binding configs to use this new broker config.

Then you are done. MQTT handles the rest. The broker will remember the last retained message sent so when the Arduino comes up after the power outage it will be commanded to the last commanded state.

Why make it hard? Use the features of the technology at hand.

1 Like

Thank you for your help.
I will try and the idea proposed by you - I hope to succeed.
It is true that I chose the hardest option but this seems to me the most reliable.
My test bench :slight_smile:

It’s the least reliable. The most reliable would be to use the retained feature built into MQTT. This is how oil rigs and industrial control systems use MQTT. Do you really think they would use it for this if it were not reliable?