State not persisting between executions in one case, but does in another

Hi,
For some reason, in the scenario below, a state I am setting is not persisting between executions.

If the lights are on and I hit the button (step 1) that triggers dimBtnHandler(evt), state.altStateDim gets set to true. After that execution completes, if I then hit the button (step 2) that triggers offBtnHandler(evt), state.altStateDim gets set to false. After that execution completes, if I then hit the button (step 3) that triggers onBtnHandler(evt), state.altStateDim somehow is set to true even though the last execution set it to false.

If I omit the dim button press from this and just trigger on and off handlers, state.on toggles between true and false, persisting between executions as expected.

I read through the SmartThings documentation on state and picked up no clues as to this behavior. What am I missing?

def initialize() {
	state.on = isOn()
	state.altStateDim = false

	if (onOffBtn && onBtnNum) {
		subscribe(onOffBtn, "pushed.${onBtnNum}", onBtnHandler)
	}
	if (onOffBtn && offBtnNum) {
		subscribe(onOffBtn, "pushed.${offBtnNum}", offBtnHandler)
	}
    if (dimBtn && dimBtnNum) {
		subscribe(dimBtn, "pushed.${dimBtnNum}", dimBtnHandler)
	}
}


def offBtnHandler(evt) {
	log("Off Button Press - Turning Off Bulbs")

	state.on = false
	state.altStateDim = false

	//DEBUGGING*****************************************
	log("debug off-press ${state.on} ${state.altStateDim}")

	for (bulb in bulbs) {
		bulb.off()
	}

}

def onBtnHandler(evt) {
	log("On Button Press - Turning On Bulbs")

	state.on = true

	//DEBUGGING*****************************************
	log("debug on-press ${state.altStateDim}")

	for (bulb in bulbs) {
		bulb.on()
	}

	doOtherStuff()
}

def dimBtnHandler(evt) {
	state.altStateDim = true
    
	//DEBUGGING*****************************************
	log("debug off-press ${state.altStateDim}")
    
	dim()
}

Here is my actual log. The dim button was hit prior to this:

app:14332021-01-21 09:28:34.428 am info debug on-press before exec state.on true, state.altStateDim true, state.altStateBright false
app:14332021-01-21 09:28:34.414 am info On Button Press - Turning On Bulbs
app:14332021-01-21 09:28:27.470 am info debug off-press after exec state.on false, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:28:27.377 am info debug off-press before exec state.on true, state.altStateDim true, state.altStateBright false
app:14332021-01-21 09:28:27.370 am info Off Button Press - Turning Off Bulbs

Here's the log with no dim button pressing:

app:14332021-01-21 09:35:39.868 am info debug on-press after exec state.on true, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:35:39.472 am info debug on-press before exec state.on false, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:35:39.464 am info On Button Press - Turning On Bulbs
app:14332021-01-21 09:35:37.129 am info debug off-press after exec state.on false, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:35:37.055 am info debug off-press before exec state.on true, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:35:37.039 am info Off Button Press - Turning Off Bulbs
app:14332021-01-21 09:35:35.490 am info debug on-press after exec state.on true, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:35:35.114 am info debug on-press before exec state.on false, state.altStateDim false, state.altStateBright false
app:14332021-01-21 09:35:35.110 am info On Button Press - Turning On Bulbs

You're not showing enough of your code to see what's going on. Also, use screenshots for logs, not copy paste -- much easier to read.

Thanks for taking a look. That was a snippet I cleaned up, aiming for clarity. I'll try to recreate the issue in a standalone app that illustrates the issue and post it.

Noted on the logs, will do.

I guess the point of my snippet was that I logged the state value was properly set at the very end of execution 1 , and then I logged the state value immediately at the begging of execution 2, and the values were not the same. There's nothing that should cause a state value to not be retained for the next execution, right?

As this is an app you could try atomicState instead.. don’t mix state and atomicState though in an app

My understanding based on ST docs is that atomicState is written to persistent storage immediately whereas state is written to persistent storage after execution completes. In my case, execution completes between button presses (as far as I can tell? no methods or waits are running), so state should be written to persistent storage.

My hesitation on moving to atomicState is that I'd need to change all of my states over to atomic due to them not being able to be combined, and I'd be doing a lot of writes because of that, presumably slowing down execution.

Well true it certainly impacts performance. Doing a global find/replace would allow you test if it makes a difference. I had many similar issues re state inconsistencies in the MQTT driver where atomicState was not an option but I solved that a different way. I wasn’t sure if it was a scope or concurrency problem.

Somewhere in the community about 3 months back there was a similar question raised with some good analysis. Worth a search if you can and if I find it I’ll post a link.

Maybe this topic ??
https://community.hubitat.com/t/2-2-4-158-resolved-bug-setting-state-variable-race-condition-c7/57893?u=kevin

Perhaps, but the link you posted was to a private communication not visible to those of us who weren’t part of the communication (or else it’s been deleted).

Sorry - it’s in the beta testers section... I didn’t realise - it’s useful info maybe worth moving up into the developers area @bobbyD?

That was a fairly detailed thread for a question I originally posted. It contains a lot of very helpful information on using "state" and possible race conditions and solutions. I was going to try and edit the "state object" page so that others can benefit from it, but for some reason, the state object page seems to have disappeared. At least I think it disappeared - I recall there was one. https://docs.hubitat.com/index.php?title=State_Object&action=edit&redlink=1

1 Like

Hubitat seem to prefer hurdles to a flat race

To be fair, they are also pretty good at answering questions in these forums. They just don't like to incorporate answers / tips into their online developer documentation. :frowning:

2 Likes

I think we should have aromic atomic state in drivers too.

How's that for de-railing the conversation? :slight_smile:

1 Like

You writing an infuser driver ?

1 Like

Lol! That's a good typo, in retrospect. ATomic.

This isn't actually a problem. You just have to be careful as to how you use them.

1 Like

What is the "real developer" way to do this? You're probably not developing right in the hub browser page like I am. To do find/replaces, I've been copying my code to Notepad, replacing, and copying back to the browser. Clearly there's a better way.

Actually that’s what I do too

1 Like

I find notepad++ (free!) a lot better (Downloads | Notepad++) . You can install a groovy-specific language extension so that it highlights key groovy keywords and features. I think there are a few different extension files out there. Here's one: Groovy user defined language for notepad++ · GitHub which you sent up from the "Language" -> "User Defined Language" menu option.

2 Likes

:laughing: Haha, got it, I guess I'm not that bad then