Persistence boot order - manual persistence and restore

Hi.
I have a binding which sets the state of the items to zero while the binding is initialized (openhab starts). it seems that during this time, the persistence is already started and will persist on “everyChange”. This leads to the situation that I can’t restore the last value before the last openhab shutdown with restoreOnStartup. Can the timing of the persistence/restore and the binding start time be controlled in the startup procedure of openhab? If yes I could start the persistence service after the bindings are fully up, thus the strategy won’t trigger on the binding start.
I tried to address the issue like this:
persist the items of interest manually on the rule “shutdown system” using item.persist(). then I reboot openhab, the binding starts and alters the items value. Since I did not have any strategy (apart from the restoreOnStartup) this means that the persistence will not take notice of the binding’s initialization and I can then use restoreOnStartup and get back to my old value (before openhab dripped).

The problem here is:

  1. I’m sure there is another way how to address this issue of this particular binding - what is the proper way of doing it? A serialization of a HasMap to file and then readback would be just fine to me… I don’t need the database really.
  2. is there such a persistence that only stores the last (one) value but having FULL manual control of WHEN to persist and WHEN to restore? Is such a persistence a light-weight, meaning it restores fast?
  3. in the rule “system shutdown” I manually persist 20 items. I have a feeling that due to the parallelism / threading of rules, openhab is shutdown while the persistence is not done on all items - as this persist() call can’t be synchronous/blocking - how could I enforce full persistence and then let the system close?

and help on this is very much needed! thanks so much!

leutholl

here is the code.

the items that need to keep the state are in the group NeedsInit. So I loop over the members and do a persist() on shutdown:

rule "shutdown"
	when System shuts down
	then
	NeedsInit?.members.forEach[ item |
			logInfo("Persist","Persist item: "+item.toString)
			item.persist()
			try { Thread::sleep(1000) } catch(Exception e) {}
		]
end

and start:

A) either restoreOnStartup hoping the timing is right or
B) using this:

What’s your thought on this?!

rule "init"
	//when System started
	when System started 
	then
	createTimer(now.plusSeconds(8)) [|
		NeedsInit?.members.forEach[ item |
			logInfo("Restore","Restore item: "+item.toString+" previously: "+item.previousState().state.toString)
			item.sendCommand(item.previousState().state.toString)
		]
end

Take a look at mapDB, which only stores the last (means actual) state. You don’t have to setup any rule, just make sure, all items, which need to be restored at startup are persisted at everyChange and restoreAtStartup. As mapDB only stores the last state, it does not deed much space, the file which stores the states does nor grow and it’s fast :slight_smile:

yes that could do the job - but do you know if this works without any persistence strategy? I’d like to have full control of when to write to and read from the database (no strategy apart from the restoreAtStartup). do you know when the restoreAtStartup is performed timingwise?

This sounds like an unsupported and unexpected behavior for a binding. The usual behavior is for an Item to be Undefined when it first comes up, not for the binding to initialize it to some value. At least that is how every binding I’ve used seems to work.

At the top of the openhab.cfg there is a polling period parameter for how often to look for updates to the various configuration files. Set the folder:persistence to some larger value. However I find it works best to make sure that rules is always bigger than items and persistence so your rules don’t start executing before Items have loaded and had their values restored.

The exact time needed will have to be discovered through experiment.

Leave the Items initialized to Undef and let the persistence restoreOnStartup initialize your Items. Or write a System started rule to initialize the Items. Do not initialize them inside your binding.

All persistence solutions allow you control over when to persist through the .persist file and by calling persist inside your rules. When to restore is controlled as I described above. MapDB is the lightest weight persistence engine. It only saves the most recent value and is perfect for restoreOnStartup. I have no idea on how fast it restores but I doubt even the fastest one in the world will solve your problem.

If you use MapDB, just have it persist every Item on every change. Then there is no need for the System shutdown rule.

Why do you sleep? I suspect the sleep is the main cause of all your Items not being persisted before OH shuts down. I’m sure OH has some checks to keep it from waiting forever on blocked threads before closing which is likely killing your rule before it finishes.

Even if you do need the sleep, why not something much shorter like 100?

Use restoreOnStartup. OH is architected and built so that you should not have to worry about this sort of thing in your rules. It is much better to rely on the features of OH than to reimplement it yourself.

Why? Do you just want to micromanage this (bad) or is there some technical reason why you need this control?

From a technical standpoint the only reason I can think you would not want to just let the everyChange strategy do its thing, particularly with MapDB which only saves the most recent value, is if there are certain intermediate values you want to throw out if OH goes down. But you’ve said nothing this far that leads me to conclude this is your current situation.

But to answer your question, yes, you should be able to just use the restoreOnStartup strategy and manually persist the values in your rules. Though I will again emphasize that if you only persist these values unchanged in a System shutdown rule it is functionally no different than using the everyChange strategy only it is less reliable.

Perhaps if you explained a little more about what your binding does, why you think you need to initialize your Items when the binding starts, and why you think you need to manually persist values I can provide more help. As it stands with the information I currently have the it sounds like you are trying to force OH to work one way where you can get the exact same functionality by doing it the way OH wants you to instead of fighting it.

very good answer thank you.
I wished it would be like that and this the way it works with every binding except one which I didn’t write. Tinkerforge in combination with the io16 brickelt and a default state. The default state is needed to set the GPIO pins configured to output at startup. Too bad the binding writes to the bricklet and(!) sets the state in the item. So the binding really doesn’t start with uninitialized. If I remove the default state config then the item doesn’t write anything also not the the item but the pins will not be configures to output. I think this is a bug. and I have wrote another thread about this.

The problem is that the restoreonstartup is executed before the binding is fully up. this is why I wanted to have manual control of when to write or read from a DB. If I keep the strategy eveyChange then the lastState of the persistence will be what the binding did as the binding startup if too late and triggers a command which the strategy will pick up (correctly).

MapDB is fine and the persist() works (forget the Sleep it was only a test) but restoring doesn’t as the binding overwrites the state. Manual restoring using previousState(true) is not supported by MapDB.

About the shutdown rule:
it seems not to wait for any Timers spinned im this rule. If it reaches the end of the rule the executable is fully down with no respect of what is running on another Thread. I solved this by a virtual Item sending ON in the shutdown rule and catching this command in another rule and do the code there. Like this, it executes everything and then stops!

I will try the timing thing but what else can I do with this “bad” binding :wink:

Note: On a power up (openhab and Tinkerforge) the LEDs on the io16 bricklet should be exactly how they were when openhab shut down. That all I want to achieve - hence the persistence. The binding should not initialize the items even when the default state make sense hardware wise.

If you delay the loading of the .persist files until after the the bindings are fully loaded (see above) then that should solve that problem. When OH loads persistence it will first load the persistence file. If the persistence file specifies restoreOnStartup it then populates the Items with the stored value. Only then will it start writing new states to the DB. But since all this occurs after the binding has come up because you delayed the loading of the persist files and rules files the initialization caused by the binding shouldn’t cause problems any longer. You will have to check in your logs to see how long you have to delay. It may be a minute, it may be 10 seconds. It all depends on how long it takes for the bindings to all come up and be initialized. You might need to put the bindings in debug logging mode so you can see when they are done loading.

Timers are not actually running until their scheduled time occurs. So if you schedule a Timer within a System shutdown rule there are no active threads running so OH has nothing to wait upon. OH only has the thread running the rule to wait upon.

Move the interaction outside of OH, drop the binding, and interact with the technology through some other means (e.g. MQTT, HTTP REST, Exec binding, etc).

This actually is the opposite to what you are asking for. You are asking that persistence load FIRST and the binding initialize the Items based on the last state. I don’t think OH can do that. The best I think you can achieve is that OH loads, the binding sets everything to 0, then your Items load and everything gets set to what they were before.

There have been a lot of complaints about OH and GPIO pins on this forum regarding startup behavior. I’m of the opinion that it is probably best not to do GPIO from within OH and to move that to something else that OH interacts with which is better able to handle this sort of situation.

ok thank you - before I try to find another solution. Will the restoreOnStartup also be executed when the Item is not Uninitialized (as the binding sets it to zero?). The documentation implies that restoreOnStartup will only restore items that are in uninitialized state. true? I hope not.

maybe my target was not very clear: I can’t change the binding - so the binding start first - setting the (wrong) values. AFTER that I want to restore to any previously saved state.

If I persist a DateTime item having the timestamp of the openhab shutdown - couldn’t I restore back in time using item.historicState()?

ITEM:

DateTime  savedDate

START UP:

logInfo("Restore","savedDate: "+savedDate.toString)
	val date = savedDate.state as DateTimeType
	logInfo("Restore","savedDate: "+date.toString)
	val jodatime = new DateTime(date.calendar.timeInMillis)
	logInfo("Restore","jodatime: "+jodatime.toString)
		NeedsInit?.members.forEach[ item |
			logInfo("Restore","member of NeedsInit: "+item.toString)
			var String s = item.historicState(jodatime).state.toString
			logInfo("Restore","Restore item: "+item.toString+" previously: "+s)
			item.sendCommand(s)
		]
```

and the SHUTDOWN

var Calendar c = Calendar::getInstance()
logInfo(“Restore”,"Calendar: "+c)
savedDate.postUpdate(new DateTimeType©)
savedDate.persist() //save timestamp to restore on startup

 
Alternatively I could wrap my GPIO pins in virtual proxy items and do some magic this way.

I don’t know.

You can do that.