FYI - .state is not always valid in rules

I thought this was worth a mention as it was suggested in another thread
When you have a rule which triggers on received command the .state of the item is not always what you think it should be.

I did not know of any recent examples of it but have since found something in the logs - which has stopped my blinds from closing at night. When the blinds don’t close an odd whine is emitted from my wife :stuck_out_tongue:

Rule:

rule "Auto Open Blinds`"
when
        Item NightState received command
then
        if (NightState.state == ON){ //it's night time
                g_FrontRoomBlinds.sendCommand("DOWN")
                logInfo("Blinds - Front Room", "It's night time - close the blinds")
        }
        else if (NightState.state == OFF){ //it's day time
                g_FrontRoomBlinds.sendCommand("UP")
                logInfo("Blinds - Front Room", "It's day time - open the blinds")
        }
        else {
                logWarn("Blinds - Front Room", "Unknown state: " + NightState.state.toString)
        }
end

In the logs:

2018-08-28 19:52:39.881 [INFO ] [smarthome.model.script.Sun Elevation] - Setting Night state ON
2018-08-28 19:52:39.959 [INFO ] [ome.model.script.Blinds - Front Room] - It's day time - open the blinds

and another example

Rule:

rule "Presence state"
when 
          Item g_PhonesPresent received command
    or  Item NightState received command
    or  Item NightStateOverride received command
then

    var preState = 0 as Number
    var newState = -1 as Number

    if (PresenceState.state == NULL){
        preState = 0
        PresenceState.sendCommand(0)
    }
    else {
        preState = PresenceState.state as Number
    }

    if (g_PhonesPresent.state == ON && g_NightState.state == ON){
        newState = 0 
    }
    else if (g_PhonesPresent.state == OFF && g_NightState.state == ON){
        newState = 1
    }
    else if (g_PhonesPresent.state == ON && g_NightState.state == OFF){
        newState = 2
    }
    else if (g_PhonesPresent.state == OFF && g_NightState.state == OFF){
        newState = 3
    }
    else {
        logWarn("Presence State", "Unknown condition")
        logWarn("Presence State", "g_PhonesPresent:" + g_PhonesPresent.state)
        logWarn("Presence State", "PresenceOverride:" + PresenceOverride.state)
        logWarn("Presence State", "g_NightState:" + g_NightState.state)
    }

    if (newState >= 0 && preState != newState){
        logInfo("Presence State", transform("MAP", "presenceState.map", newState.toString))
        PresenceState.sendCommand(newState)
    }
    if (newState < 0){
        logInfo("Presence State", "newstate is less than zero")
    }
end

and in the logs

2018-08-28 19:52:40.065 [WARN ] [marthome.model.script.Presence State] - Unknown condition
2018-08-28 19:52:40.115 [WARN ] [marthome.model.script.Presence State] - g_PhonesPresent:ON
2018-08-28 19:52:40.144 [WARN ] [marthome.model.script.Presence State] - PresenceOverride:OFF
2018-08-28 19:52:40.176 [WARN ] [marthome.model.script.Presence State] - g_NightState:ON
2018-08-28 19:52:40.212 [INFO ] [marthome.model.script.Presence State] - Night time, Someone home

I’ve not noticed this before and can now see a few examples in the logs. So, there is a bit of rewriting for me to do to counter this. A bit of a headache but there you go :slight_smile:
Hopefully posting this helps someone else reading it.

So, the fix is to not rely on item.state but rather pick up receivedCommand.

1 Like

I have a similar issue, but mine sounds like a ‘tut’ noise.

I’ve asked some friends if I should upgrade, but they all agree that my mistake was moving from Girlfriend V9 to Wife V1.

Upgrading to Wife V2 is extremely costly and a painful process.
They advise that I should put every effort into ensuring that Wife V1 runs smoothly instead.

Any advice on this subject would be welcomed

As for the blinds?

Maybe a wrist watch & manual approach would stop the whining noise?

Good luck :wink:

The sad thing is, I can’t even claim that joke as mine :frowning_face:

Upgrading to Wife V2.0

The reason why is that OH will trigger your received command Rule even before it updates the Item registry with the new state. So for the first few dozen milliseconds as your Rule runs the Item probably will not yet reflect the new state caused by the command.

And, if you are using autoupdate=false in your Item config, the Item does not automatically change state when it receives a command. This is handy when the device reports its state back to OH. That way we don’t have to assume that the command worked and rely on the device to report its current state.

But this means in your receivedCommand Rule, the state of the Item may take even longer to change to the new state, and if the command failed it may never reach the new state.

So, if what you really care about the state of your Item in your Rule, you should probably be using received update or changed as your trigger. If you care what the command was but not necessarily what the state of the Item is, you should be using received command as the trigger and receivedCommand in your Rule.

It’s a subtle but important distinction.

And while we are on this topic, if you have something like:

MyItem.sendCommand(ON)
logInfo("Test", MyItem.state.toString)

Don’t expect you will see ON in your logs. There is almost certainly not enough time for the Item registry to have updated MyItem by the time the logInfo line runs.

1 Like
if (WifeV1_Whinning.state == ON || WifeV1_Tutting.state == ON) {
    say("Sorry Darling!")
    Bedroom_Blind.sendCommand(0)
}
3 Likes

Chuckled to see others have the same wife bugs… :slight_smile:

When would this be useful? I see a useful counter to it where it internally waits for the update to happen before firing the event.

I saw this happen very early on when dabbling with OH.

I use update to push a value and not fire rules (because I don’t want them to) and sendCommand to trigger the rules. It’s a bit of a pain if this is the case.

As above though, I think it would be beneficial to have a switch which forced a block on the rule trigger until the state actually changed. I can’t see where there would be a use for triggering a rule on command change but state may or may not be updated? Curious about that one.

As in, when would you not want the Item to autoupdate from a command.

In truth, this is the idealised condition for OpenHAB where an Item is associated with a real device. You send it a command, a binding processes that into some transfer to an external device. Some time later, when the device feels like it, or the next poll happens, an update arrives into the binding and is used to update the Item. The response from, say, a dimmer to command ON might be “100%”. The Item reflects the real world.

In reality, people want an instant response on their UI; some devices don’t produce feedback at all; we use virtual Items not associated with real devices.
So OH has an ‘autoupdate’ feature.
I find it helpful to think of autoupdate as another binding, the same process is followed of command->Item processed (eventually) into update->Item. ‘Eventually’ is fast but a finite time.

It would probably all make more sense if they had chosen autoupdate=“false” as the default setup for Items, but that’s not going to change now!

Example of rule that exploits the difference between command and update

Don’t know quite what you’re doing, but it may be useful to set autoupdate=“false” for your Item and then you’ll always know what’s going on. Your rule dealing with command can choose to issue Item.postUpdate(receivedCommand) when required. Note that’s another asynchronous process, no immediate effect!

In this instance, it’s the blinds. The widget has 3 controls; up, down and a slider for anything in between.
When up or down is pressed I send the command to the BT interface and the blind whirs into life.
If I move the slider, on stop, it fires another rule with a command. I then pick up the value and send that percentage to the BT interface. The blind moves to that position.

What I have working, due to the difference in them, is when up or down is sent, I get a positional update from the blind and move the slider by and label percentage by posting updates to it. This gives realtime feedback that a) the blind is actually moving and b) an ETA of when it’ll be fully open or closed (measured in days :D)

Not doing this does not move the slider if the up or down is pressed.

Can I change it around to work differently? A number of options are available, just trying to find the most elegant.

OK, that makes sense. It’s an option I can have for the above problem I think. I can set auto-update off and then feed it back with positional information. I think.

It does sound like you’re in exactly the situation where you don’t want autoupdate! Luckily for me I’ve never got involved with shutters. You have the choice of that instant-response UI, or the real-world reflection. There’s the beauty of OH, tailoring the limitations of a device to your preference…

I suspect you might end up with an introduction to ‘virtual Items’ and ‘visibility’ in Sitemaps, allowing the buttons to be temporarily replaced with “In motion” or suchlike. Leaving that to shutter experts …

rossko57 described it pretty well but I’ll take a further step back.

Items are the model of your home automation. In the ideal world, as rossko57 describes, the Item would always reflect the actual state of the physical device it connects to. However, to achieve that it requires the devices to always return state changes on the device back to OH in a timely manner (milliseconds). More often then not, that doesn’t happen and we have to infer the state of the Item based on polling or based on just assuming that when we sent a command the device changed to that state.

OK, now let’s talk about what it means to send a command. Sending a command means you are asking a device to do something. For example, when I MyLight.sendCommand(ON), I’m asking MyLight to turn on. Now lets assume that MyLight always immediately reports its state back to OH whenever it changes. Now let’s assume something went wrong and the light failed to turn on after we sent the command.

  • autoupdate=true: in OH MyLight will have the state ON because we are assuming that the device received and processed the command correctly
  • autoupdate=false: in OH MyLight will remain OFF because the light failed to process the ON command and never sent a message back to OH telling it turned ON

So in this case, using autoupdate=false means that MyLight actually more closely matches reality.

So in my mind is why would you ever use autoupdate=true, not autoupdate=false. The reasons are:

  • we don’t live in a perfect world; probably more devices fail to report back than those that do meaning our only choice is to assume the device processes the command successfully
  • the Item may be a proxy Item or an Unbound Item not directly connected to a device to give it feedback when it changes state
  • there may be unique timing requirements where you can’t wait for the device to report back its new state

Now let’s think about Rule triggers.

The developers of OH decided early ON to have three ways to trigger a Rule based on Item events:

  • received update: triggers when an Item is given a new state, even when the new state is the same as the old state. This is useful in cases where you want to do something every time the Item gets touched for any reason (e.g. processing the results from a periodic call to an API where the response may be the same but you still need to do something).

  • changed: triggers when an Item changes state. This is useful when you need to do something only when a state changes (e.g. temperature changes to control HVAC).

  • received command: triggers when something (person, sitemap, Rule) deliberately takes action to cause a device to change state. This is useful in cases where you want to distinguish between updates that may occur regularly because of polling and an action that was deliberately initiated. But why trigger the Rule before the Item changes state? I wasn’t privy to any of the deliberations that went into that decision but I think it so that we can trigger Rules like a check that the action took place. For example, we can set a timer and when the timer goes off check to see if MyLight is actually ON after sending it the ON command and if not send the command again or send an alert. If we wait for MyLight to actually change state before triggering the Rule we can’t do that.

All of the above can be further narrowed down to only trigger Rules based on certain states (e.g. changed from ON to OFF).

This is turning into, for me at least, an interesting conversation :smiley:

I understand better now how items are supposed to work but still, there is a problem (in my head)

I have an item (Blinds). I have two buttons in an HabPanel widget which send it a command - UP or DOWN.
Now, if I understand you, in the correct world the binding would react to this but only change the state to UP or DOWN once it’s confirmed that the physical action has taken place. That would be awesome and solve one of my problems - how do I know the blinds are moving. I can easily put that into code.

However, what I don’t understand is how do you know what the action should be?
If an item had two properties - “current” and “requested” (it could have a third - actioned if they equal)
If that were the case then I can see the example working. My rule or binding would say “ok, it’s updated / received command, what is it now and what is it wanting. Action it, wait for confirmation and then set the current state”

I’m not seeing how I can put the intended use into use in a rule which calls a http call.
Conceptually, I have -
Command received, if Up send up then loop polling for position. When position 100% then set state = UP.

But that conflicts with what you’re saying?

In OpenHABs event-driven model
send command UP
Set something to “in progress” if you like, else just go off and do something else.
-later-
Blind reports 100%, via binding I suppose, and OH updates the relevant Item.
Trigger a rule off the Item change to do whatever, send the message it’s completed, say.

No loops, no waiting.

Of course, the exact to-and-fro with the physical device depends on teh technology you are using. Some blinds provide no feedback at all - that’s okay, you can make OpenHAB work with what its got.
Example, send an UP command and start a timer that runs for blind’s max duration.
Go off and do other things.
-later-
Timer completes, updates Item (and you hope its worked!)

Aha! This is something we haven’t covered. There is no UP or Down state for a RollerShutter. A RollerShutter only carries a PercentType as it’s state. So this is another reason why received command is different. The command may not actually match the state of the Item.

You would detect that the RollerShutter is moving, in the perfect world, because the state of the RollerShutter (that number between 0 and 100) starts changing. So you would want to trigger a Rule based on a changed trigger. You can tell what direction the shutter is moving because an implicit variable called previousState that has the previous state before the change so you can compare that to the current state.

if(previousState > RS.state) // going down

But not all rollershutter devices report their state back or report it back quickly enough, so you have to either assume it started moving when it received the DOWN command or set a short timer after the DOWN command is received and to make sure that it is changing based on how quickly/frequently the device report’s its state back to OH.

Anyway, this is another reason why the received command Rule trigger can’t wait for the Item to reach the state it was commanded to. Many commands to many Items will not match the state of the Items. But you might still want to trigger your Rule based in the command.

Since you are using HTTP then you are in the not/ideal case. You get no independent feedback about the state of your device. So you have to assume the device starts moving when it receives the command or you need to write code to double check yourself. That is what rossko57 is referring to in the “go off and do other things, later a Timer completes and update the Item.”

You definitely do not want to sit in a loop inside the Rule polling in a while loop.

Hi,

Very interesting post! Due to it I changed all my rules and use implicit variables (such as ReceivedCommand) for my switches. My relay’s always give me feedback so I’ve also set the autoupdate as false and interpret the received feedback.

Now, I’m still a bit struggling for my dimmers. It works but it seems to me that it is not the perfect way to do it.

I now have this rule:

rule "Send Command Relay22"
when
    Member of Relay22 received command
then
Thread::sleep(10)
    var relayswitch = triggeringItem.name
    var input = triggeringItem.state.toString
    var result = transform("JS", "SendCommandDimmers.js", input)

    logInfo("Bijkomende info", "receivedCommand is dus " + receivedCommand + " en dit voor item " + relayswitch + ". Input is nu " + input + " en het resultaat " + result)    

    switch relayswitch{
     case "GF_Eetplaats_Eettafel_Licht": SendCommand_GF_Eetplaats_Eettafel_Licht.sendCommand("S0" + result)
     case "GF_Living_Zitplaats_Licht": SendCommand_GF_Living_Zitplaats_Licht.sendCommand("S1" + result)
     ...

     }

I have 6 dimmers, all combined in a group “Relay22”. When one of them receives a command, the rule is triggered. The received command (percent type) is transformed into a string which I send to the Relay.
Now, to get the actual (or presumed :slight_smile:) state, I have to include a Thread::sleep(10) because otherwise he takes the old state.

My question, is this the way of working in this case, so to put a sleep in the rule?

Thx

So why are you not using receivedCommand here instead of the Thread::sleep and triggeringItem.state.toString? Is this to handle ON/OFF commands? Maybe a changed trigger would be better.

What binding are your relays linked to? Depending on the binding you may not need the rule at all.

Hi,

Because I get an error using this (partial) rule:

rule "Send Command Relay22"
when
    Member of Relay22 received command
then
Thread::sleep(10)
    var relayswitch = triggeringItem.name
    var input = receivedCommand
    var result = transform("JS", "SendCommandDimmers.js", input)
...

The error occurs on the var “input” in the transform brackets saying: “Type mismatch, cannot convert from Command to String.”

It is not exactly to handle ON/OFF commands but to handle the PercentType carried by a Dimmer Item.

I’m using the UDP/TCP binding sending a simple string tot my relays.

Example:

Dimmer  GF_Eetplaats_Eettafel_Licht   "Licht Eettafel"   <light>    (Home, GF, GF_Lichten, GF_Eetplaats, Relay22) [ "Lighting" ]
String  SendCommand_GF_Eetplaats_Eettafel_Licht "Send Command GF_Eetplaats_Eettafel_Licht [%s]" (SendCommandRelay22) { udp=">[10.10.1.22:1001:default]" }

transform requires three Strings are arguments. You need to convert receivedCommand to a String. Luckily that’s as easy as receivedCommand.toString. Just like you have triggeringItems.state.toString.

You could move the switch statement to a JavaScript transform but it doesn’t save you much work.

Why didn’t I think of that? :roll_eyes: :grin:

Thanks!!!