Weird behavior when querying item state

I have a switch item to toggle some bool value which is later evaluated by some cron rule. The switch is just some logical item, i.e. not device based item. Now sometimes when I flick the switch and inside query the state I get the wrong state value. E.g. I switch to ON, and in the rule the queried state returns OFF.

The rule looks like:

rule "cron rule activate"
when
    Item TriggerTomorrow received command
then
    logInfo("trigger", "DEBUG: Switch state: " + TriggerTomorrow.state.toString)
    if (TriggerTomorrow.state == ON) {
        logInfo("trigger", "Switch: Turn on tomorrow")
        turnOn = true
    } else {
        logInfo("trigger", "Switch: Ignore tomorrow")
        turnOn = false
    }
end

The log output looks for example like:

2018-03-07 00:39:38.731 [INFO ] [ipse.smarthome.model.script.trigger] - DEBUG: Switch state: OFF
2018-03-07 00:39:38.733 [INFO ] [ipse.smarthome.model.script.trigger] - Switch: Ignore tomorrow
2018-03-07 00:39:38.727 [ome.event.ItemCommandEvent] - Item 'TriggerTomorrow' received command ON
2018-03-07 00:39:38.737 [vent.ItemStateChangedEvent] - TriggerTomorrow changed from OFF to ON

You can see the switch state changed to ON, but evaluating the state returns OFF. Why is that? I don’t understand this. Is this a race condition? I would expect that the item state is already updated when the rule is executed and that I can safely query it?

I’m running the OpenHAB 2.2.0 Docker image on Debian Stretch.

Your rule triggers on a command TO an Item.
At some time, OH’s autoupdater feature will receive that command too, and will autoupdate the Item state to the new value.
So yes there is a race, your rule may or may not get to any given stage before the Item autoupdate takes effect.

Choosing rule triggers carefully usually pays off - perhaps triggering on Item changed is more suited for your task?

1 Like

Rules trigger based on events on the event bus. For our purposes here let’s assume there are three events: command, update, changed.

There is also an Item registry which maintains the current state of your Items. It is from this registry that MyItem.state gets the value that gets returned.

This is the flow of a command:

  1. Binding/UI/Rule issues a command on an Item
  2. Command event sent to event bus
  3. These steps occur in parallel
    a. Rules with a command trigger on that Item trigger
    b. Item registry receives the command event and updates the registry with the new state
  4. The Item registry sends an update event to the event bus
  5. The Item registry sends a changed event to the event bus (if the state changed)

So not only is it possible, it is probably that the Item registry will not yet have been updated when your Rule starts executing. That is your race condition.

As rossko57 indicates, one way to deal with this is to use received update or changed to trigger your rule. Another way is to use the receivedCommand implicit variable instead of TriggerTomorrow.state. receivedCommand will be populated with the command that triggered the Rule and does not go back to the Item registry to get the state and therefore does not experience this race condition.

Thanks for you thorough explanation. Makes sense. So at least I know what’s going on and can solve this (and that I didn’t just forget to properly initialize or whatever) :slight_smile:

But… maybe I’m missing something here…shouldn’t the execution environment make sure that all states are updated before any of the triggers are called? That would simplify things for the user and make things more robust, because he/she doesn’t have to worry about such not really obvious implementation details.

More generally speaking, as a new user, and even with long years of software development experience, I find it pretty hard to create even comparatively simple rules. And even though OpenHAB documentation is great for an open source project! But still… For instance yesterday I spent a whole evening trying to understand why a simple subtraction of two numbers failed with an exception, starting with an unclear error message to figuring out that there are different number types are involved and which ones and how to convert them, eventually leading to new unexpected effects. But yea, I’m getting off-topic … :wink:

That isn’t how the event bus works. I wasn’t involved in the design or building of it so cannot explain the reasoning. All I can say is that it was a deliberate decision to implement it this way.

The Rules DSL has its weaknesses for sure. If you are a developer you might be happier using a more familiar language through the JSR223 binding. This lets you write your Rules using Jython, JavaScript, or Groovy. As the Experimental Rules Engine matures, which uses JavaScript as the coding language (I expect the other two to come along eventually as well) I expect it will eventually replace the Rules DSL as the default.

I hate the way numbers work in the Rules DSL. My recommendation when working with numerical values and states:

  • Always cast the state from a Number Item to Number
  • Avoid the use of primitives
  • The default class that the Rules DSL assigns numerical results to is BigDecimal, which is of type Number so if you do need a primitive (this should be rare) you can get at it by calling .intValue et al.

When you get further into it, you’ll find that the subtle differences between trigger events have their uses.
Consider some real device, where there may be a delay between command and response/update.
You can choose not to have autoupdate in effect, so that your Item reflects the real device (rather than a hoped-for outcome).
You can set up different rules doing different things upon command and upon update.

Equally, it takes some getting used to when dealing with asynchronous events. I suppose that reflects the nature of this world though.

1 Like

I guess I should have reacted on changed instead of received command then. I guess I was expecting changed to be used for changes reported by a device, and it felt natural to react on received command for that button. And well, it worked, most of the time :wink:

But still… When I disable autoupdate and handle the state update myself, it probably would be obvious that things are async and that I can’t rely on the queried state when the command rule is triggered.
But otherwise, as I understand it, the state (auto)update will always be handled locally, and it actually doesn’t matter what the device is doing asynchronously or not, like whether it takes 10s to update it’s internal state, right? Or does the autoupdate depend on other things, like feedback from a device? What would speak against first doing the autoupdate and then triggering the rules?

I think I can see your point, from a software design perspective, that the autoupdate is treated async like a true async update. But from an “ease of use” perspective it may not be optimal.

Maybe it would have been more obvious if the rule syntax would require an explicit variable name, instead of the implicit receivedCommand (which you have to know about). Like:

    Item MySwitch received command ON
    Item MySwitch received command OFF
    Item MySwitch received command as fooBar

    if (fooBar == ON) { ... }

Whatever… What remains is that the user experience was suboptimal, for me, in this case. As I said, being new to OpenHAB I have only a limited view on the system, but I feel it’s pretty complicated to write rules, often it feels needlessly complicated.

I’m not sure if it has to do with being a developer. In this case I rather have my joe user hat on. I wonder how less developer people cope with that, say my dad, who is interested in tech stuff, but not a developer? I just can’t imagine that a non-developer has an easier time writing rules. It already starts with that it’s not clear what language that is and “how things would be right”. Sometimes it seems to be Java, but other times it doesn’t.
Just yesterday I found that comment in the docs that a return has to be followed by a ;, huh?? Everywhere else it doesn’t matter. (It even seems I can leave out things like function () or quotes on strings (not sure, didn’t see an API description in the docs yet))

Actually I think that a language like JS might make it simple for everyone. It’s clear what it is. You find a bazillion tutorials and help on the net.

Glad it’s not just me :grin:

Interesting, actually for me it seemed more reliable to consequently convert to stupid ints and floats.

If you look at the log output they are not quite in chronological order which makes senses after reading the command flow above.
You can try to change the rule trigger as above or use receivedCommand as @rlkoshak said above or
You could try to use the implicit variable triggeringItem and see what happens or you could use Thread::sleep(50) 50 milliseconds to wait for the item registry to have updated but that’s a bit hacky.

Regards

There are there sources of these complications. One comes from the fact that that is how it was implemented and no one has cared enough to change it. This is an open source project. Any code that gets written is because someone cared enough to donate there time to update the code. One slice comes because of the underlying architecture of OH. But by far the biggest source comes from the fact that OH had to deal with all the little differences and oddities in behavior for over 200 separate technologies and APIs.

From the a docs:

autoupdate=“false” is a special instruction which keeps the current state of the item, even if a command has been received. This way, the Item is unchanged unless you explicitly post an update to the item.

The purpose of autoupdate is to allow for for a separation from the command and the update for those cars where there is some other event or sensor that confirms the device has entered the new state.

For example, you have a light that you can send a command to and then the light sends a message back confirming the light changed state. You would use autoupdate false so the Light’s Item will not change state in the command and instead wait for the confirmation message to change the Iten’s state.

When and whether to use autoupdate depends on the bindings being used and how that technology works. But realize there are some technologies that don’t provide any feedback and you will need to use some other sensor to provide confirmation that they action took place or you might just need to live with the fact that you have no way to know if your light is really on after sending a command to turn it on.

Like.i said before, I wasn’t privy to the discussions when this was decided, but I have enough experience to believe it was a compromise to handle these sorts of differences between how various technologies work and various use cases. There are probably some very compelling use cases where it makes sense to receive the command immediately rather than waiting for the state change itself or cases where over is using autoupdate false but need to trigger a rule before the device reaches the command state.

Note: The rule syntax is based on Xbase and as a result it is sharing many details with Xtend, which is built on top of Xbase as well. As a result, we will often point to the Xtend documentation for details.

The problem for most users is that when they lose the primitives the lose autoboxing/unboxing like that get work every other type, toString, etc causing a lot of extra work to do something as simple as postUpdate .

The base language Xtend runs on the JVM and all the basic Java libraries are available and that is where some Java concepts come in. But it is it’s own language with all sorts of syntactic sugar that lets you call get* methods like accessing a data member and stuff like that.

The whole return; thing was something we discovered through experimentation. I don’t think it is a documented feature of Xtend at all. It is just something we discovered.