Changed vs received command, when does the state change exactly?

Hello,
I’m new here. I’ve been using openhab for about 1 year. Mostly very simple stuff. Now I’m trying to control my lights.
My setup is as follows: 3 lights which I can control via http (REST). The lights are dimmable. I can read their status but only digital, so on or off. Hence when someone touches the physical switch to turn the lights on, openhab doesn’t know which level they are set to. I have two groups of items: dimmer and status:

Group:Dimmer:MAX gLightCorridors "The max corridor light is [%d]"
Group:Number:MAX gLightCorridorsStatus "The status of the light"

Dimmer LightF1Corridor "Light Floor 1 Corridor" <light> (gLightCorridors)   
Dimmer LightF2Corridor "Light Floor 2 Corridor" <light> (gLightCorridors)  
Dimmer LightF3Corridor "Light Floor 3 Corridor" <light> (gLightCorridors) 

Number LightF1Corridor_State  "Light F3 corridor state [%s]" (gLightCorridorsStatus) { http="<[lightF1CorridorCache:10000:REGEX(.*?<val>(.*?)</val>.*)]" }
Number LightF2Corridor_State  "Light F3 corridor state [%s]" (gLightCorridorsStatus) { http="<[lightF2CorridorCache:10000:REGEX(.*?<val>(.*?)</val>.*)]" }
Number LightF3Corridor_State  "Light F3 corridor state [%s]" (gLightCorridorsStatus) { http="<[lightF3CorridorCache:10000:REGEX(.*?<val>(.*?)</val>.*)]" }

I have 2 rules which react to members of these two:

rule "dimmer changed"
when
    Member of gLightCorridors received command // trigger was set to changed before
then
    val dimmer = triggeringItem
	var state = dimmer.state as Number
	val int x = state.intValue
    // get the IP address
    logDebug("light.rules", "Received command:" + receivedCommand)
    logDebug("light.rules", "Light target state:" + x.toString)
...
end

rule "light state changed"
when
    Member of gLightCorridorsStatus changed
then
    val light = triggeringItem
    val state = light.state as Number
    val int x = state.intValue
   // get the corresponding dimmer
    val dimmer = gLightCorridors.members.findFirst[ t | t.name == 
    light.name.split("_").get(0) ]
    // check if x = 0 & the dimmer is also above 0
    if (x == 0 && dimmer.state > 0 ) {
        dimmer.postUpdate(0)
    }
    if (x > 0 && dimmer.state == 0 ) {
        dimmer.postUpdate(100)
    }

end

The problem I face is the following: when that status changes to e.g. on, I’d like to set the dimmer to 100 without trigger the rule which sends out the http request. I first hat the trigger for the first rule as changed. But then I read in the Documentation that for this case I’d need to use received command. So I changed that. But the receivedCommand only contains the target value and the implicit variable previousState is not set (as would be when the trigger is set to changed) . So when the dimmer in the GUI is changed from 40 to 50 it’s 50. In the documentation is also say, that the received command triggers before that state is updated. So I thought I can use the state to get the previous value. But when testing I see that this is not always the case. Sometimes the receivedCommand is the same as the state of the item. So I’m confused.
Am I missing something, is the documentation wrong or is the implementation not correct? Any ideas how to resolve this?

1 Like

If you need to know the previous state in your Rule and you can’t trigger the Rule using a changed trigger, you need to get the perviousState some other way. Your best option is to set up persistence and use MyItem.prviousState().state to access the previous state of the Item.

The docs are correct, your Rule will trigger before the Item’s state is updated for received command, but the Item’s state will be updated in the background while the Rule is running so you cannot rely on the Item’s state being the previous state or the received command state. Which it is depends on timing.

1 Like

Quick answer. Guess I’ll have to look into persistence then.
Thanks for your answer and clarifying/pointing out the timing issue.

I find it helpful to think of commands sent to an Item in this context; in an idealised openHAB commands get passed on to real devices by bindings. They don’t change the Item’s state directly, because eventually we hope the real device will respond with a new status, and the binding will then update the Item.

Of course, not every Item is bound to a real device, and some devices don’t respond very quickly, if at all. So they designed in ‘autoupdate’ - which acts like a psuedo-binding, listening for commands and when it gets one, updating the Item. That takes a short time, and of course it’s not especially likely to be triggered before any rule also listening for commands.

They chose to enable autoupdate by default for each Item, as in many cases it helps make the user interface look responsive to button pressing.

You can choose to disable autoupdate for an Item, and in many cases that’s a good idea if you’re getting timely feedback from a real device.

It sometimes proves useful even for unbound Items - you can process an incoming command with a rule, and choose what (if any) updates you make to the Item in response.

I find this philosophy can help clarify which rule triggers to use - are you trying to respond to real world events (state change), or to directives from UI or other rules (commands) ?

1 Like