Restore z-wave state of items from presistence after items file is changed

There is a presistence functionality if OH starts to reload the state of items from presistence, very good.

But, if I change an item file at runtime with z-wave items in it, all states of the items are lost until the device sends an update of the state.

Is there a way to prevent this or to restore the current state from the presistence file after items file is changes?

My problem is, that all door/window sensors states are lost and I have to go to every window/door and open/close it one time to get the current status back

I found this one to restore a single item:

item:
Group gRestoreState
Number DoorSensor04_Battery “[%d %%]” (gRestoreState)

rule:
gRestoreStartup.members.forEach[item | item.sendCommand(item.previousState(false,“mapdb”).state.toString) ]

How to trigger this rule automatically if needed? Which means after item file changed.

Update:

This is not working:
gRestoreStartup.members.forEach[item | item.sendCommand(item.previousState(false,“mapdb”).state.toString) ]

only if used by single item:
DoorSensor04.sendCommand(DoorSensor04.previousState(false,“mapdb”).state.toString)

How to fix it?

Update:

solved too
this is working
gRestoreState.members.forEach[item | item.sendCommand(item.previousState(false,“mapdb”).state.toString) ]

only if all of the values have a valid presistence set

to be sure send this comamnd before somewhere
forEach[item | item.persist() ]

Only ope nquestion:
How to trigger this rule automatically if needed? Which means after item file changed and item state got lost due to this.

Are you sure you want a solution this complicated?

A plain, simple setup of a persistence service, for example mapdb, works fine for all items, regardless which binding is used.

Install MapDb persistence and configure your items like this:

Items:

Group gRestore 

Switch Test_Switch "Test Switch"  (gRestore)

mapdb.persist:

Strategies {
everyMinute	: "0 * * * * ?"
everyDay        : "0 0 0 * * ?"
default = everyChange
}
Items {
gRestore* : strategy = everyChange, restoreOnStartup
}

It doesn’t when you edit an Items file without restarting OpenHAB.

The only way I can think to detect file reload is to have a rule firing on some Item change and test to see if it changed to UNDEF. Choose something like a virtual Item (controlled by your rules) rather than something bound to a real device, just to avoid UNDEF appearing due to say a communication failure. Choose something normally persisted to avoid triggering at system reload.

Upps, didn’t read the last part of the topic header … :sunglasses:

In my experience it does indeed work for both restarts of OH and edits to .items files. If this is no longer the case I would call that a regression.

restoreOnStartup has always initialized my Items from persistence for file edits as well. But I admit it has been awhile since I’ve done a lot of editing.

You are right, thiw will work. But I have to set presistence for zwave values manually because thsi rule does not work after reload of item file.

I played around with this last evening and foud pout, that is was notworking at all.

What I have done:
item:
Group gRestoreState

Contact DoorSensor01 “AEOTEC [MAP(de.map):%s]” (gRestoreState){ channel=“zwave:device:15a7a49f3a6:node3:sensor_door” }
Number DoorSensor01_Battery “AEOTEC Battery [%d %%]” (gRestoreState){ channel=“zwave:device:15a7a49f3a6:node3:battery-level”}

Contact DoorSensor02 “AEOTEC [MAP(de.map):%s]” (gRestoreState){ channel=“zwave:device:15a7a49f3a6:node5:sensor_door”}
Number DoorSensor02_Battery “AEOTEC Battery [%d %%]” (gRestoreState){ channel=“zwave:device:15a7a49f3a6:node5:battery-level”}

At the end, the presitence is not set by my rule:

rule for saving presitence
gRestoreState.members.forEach[item | item.persist(“mapdb”) ]
This looks like it is working, I checked the stored values with rest api and they are all correct and all does exist

gRestoreState.members.forEach[item | item.sendCommand(item.previousState(false,“mapdb”).state.toString) ]
This looks like it is not working. The values are not set correctly on at all not set.

If i use the item itselve, it is working
DoorSensor01_Battery.persist(“mapdb”)
DoorSensor02_Battery.persist(“mapdb”)

DoorSensor02_Battery.sendCommand(DoorSensor02_Battery.previousState(false,“mapdb”).state.toString)
DoorSensor02_Battery.sendCommand(DoorSensor05_Battery.previousState(false,“mapdb”).state.toString)

So the problem is the group config. This was not correct recognized by OH?

any idea?

I found the real problem:

It looks like some values cannot be set correctly
2017-05-12 09:18:29.327 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘PresistenceWiederherstellen’: The argument ‘command’ must not be null or empty.

This works well:
gRestoreState.members.forEach[item |
logInfo(“Logger”,"Itemname speichern: "+item.name)
logInfo(“Logger”,"Itemname speichern: "+item.state.toString)
Thread::sleep(2000)
item.persist(“mapdb”)
]

This crashed on some of the items with the above error message
gRestoreState.members.forEach[item |
logInfo(“Logger”,"Itemname laden: "+item.name)
logInfo(“Logger”,"Itemname laden: "+item.state.toString)
Thread::sleep(2000)
item.sendCommand(item.previousState(false,“mapdb”).state.toString)
]

Not sure why. Any idea

1 Like

I I use this, it is the same:

DoorSensor01.persist(“mapdb”)
==> no error

DoorSensor01.sendCommand(DoorSensor01.previousState(false,“mapdb”).state.toString)
==> same error as above:
2017-05-12 09:18:29.327 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘PresistenceWiederherstellen’: The argument ‘command’ must not be null or empty.

Rest API tells me, that the value is correct stored in mapdb.

I think I found the error.

DoorSensor01 is a contact. on contact it looks like sendCommand is not working only postUpdate

Can someone verify this? and does it work if I use postUpdate?

It makes little sense to sendCommand to a Contact type usually, the real device is passive and cannot do anything with a command, though I don’t see why you cannot.

It does make sense to use postUpdate for restoring, after all you probably do not want the target item to actually do anything, you just want to restore the state.

I do think you should set up your persistence properly for automatic onChange, and not rely on a rule to save it.

I am intrigued by the suggestion that restoreOnStartup should work with an items file reload, but I cannot test this (not OH2 user) - would someone with working system try it? Checked it out in OH1 and it works fine. I really thought it did not.

Hi rossko57

I’ve tested it. my zwave devices stayed undefinied after reload of items file. And this causes alarm because of my door/window sensors :wink: or heating or status of siren

This is why I look for a solution to reload current state after reload of item file. And now it is working.

But there is another strange thing. gRestoreState membership does not work. If I add now items to this group they will not be stored in the presistence file. looks like it is a problem with OH2. Only restart of OH2 fixed this problem.

But I can live with this.

I’m afraid its not clear what is and isn’t working for you now.

This is a “well known” problem


sorry for confusing you.

after change from sendCommand to postUpdate everything is working well. With sendcommand the rules runs into an error and does not go to the end of the rule.

2017-05-12 09:18:29.327 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘PresistenceWiederherstellen’: The argument ‘command’ must not be null or empty.

But after some playing now it is perfect. And postUpdate does what I want, just update the value to do not any action on a zwave-device

I found some weird behavior during testing (only checked zwave items):

Some items get their state restored after items file changes, some do not.

Persistence service used: MapDB through group config (gRestore)

a) First test:

motion.items

...
Switch FibUniSens1_1	"Motion Hallway down [%s]"	<motion> (gRestore)  {channel="zwave:device:158b44ebf65:node23:sensor_binary1"}
Switch	FibEye1_Motion_S	"Motion Hallway up [%s]" <motion> (gRestore) {channel="zwave:device:158b44ebf65:node3:sensor_binary"}
...

lights.items

...
Switch FibFGS223_2_Sw_2 "Living Room 4" (gRestore) { channel="zwave:device:158b44ebf65:node31:switch_binary2" }
...

motion items edited at 20:54:
2017-05-12 20:54:12.389 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model ‘motion.items’

events.log

...
2017-05-12 20:54:13.613 [ItemStateChangedEvent     ] - FibFGS223_2_Sw_2 changed from NULL to OFF
...

No indication that the two items from the motion.items file (FibUniSens1_1,FibEye1_Motion_S) got restored through MapDB. But an item from lights.items file (FibFGS223_2_Sw_2) got restored correctly.

b) Second Test:

lights.items edited at 21:18:

2017-05-12 21:18:38.921 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'lights.items'

Again no indication that the two items from the motion.items file (FibUniSens1_1,FibEye1_Motion_S) got restored through MapDB. The item from lights.items (FibFGS223_2_Sw_2) again got restored correctly.

events.log:

2017-05-12 21:18:39.902 [ItemStateChangedEvent ] - FibFGS223_2_Sw_2 changed from NULL to OFF

I cannot make any sense out of that. The only difference I can see at the moment is that FibFGS223_2_Sw_2 is a mains powered device and FibUniSens1_1 and FibEye1_Motion_S are battery operated devices.

That is probably correct, by design. Restore should just happen invisibly and not trigger update events.

Seems possible that real updates from real (mains) devices could beat the restore mechanism to it (or rapidly overturn a restored state). As I understand battery zwave devices, updates are very infrequent.

Please try to restart OH2 before testing. Sometimes group mebership is not working correctly. Maybe this is the problem why not all are restored.

In my case, this was the problem.

You can verify group membership with this little rule

item:
Switch groupmembership

rule "List groupmembership"
when
Item groupmembership changed to ON
then
gRestoreState.members.forEach[item |
logInfo(“Logger”,"Itemname laden: "+item.name)
]
groupmembership.postUpdate(OFF)
end