Rule firing after rule changed value

I’ve got a HVAC that has a secondary WiFi controller that I am sending commands to with the HTTP binding but because it also has a main controller I need to poll the data to update the virtual OH items and therefore HABPanel. Today I had the logs up and noticed that every time a change is made on the HVAC controller it updates the OH value which triggers the OH rule to run too. As I’m using postUpdate this was unexpected behaviour as the documentation says “Change the status of an Item without causing any implicit actions. Can be used to reflect changes that may be caused by other means.” so why is it doing this?

2019-08-01 14:59:44.729 [vent.ItemStateChangedEvent] - DaikinPower changed from 0 to 1
2019-08-01 14:59:44.758 [vent.ItemStateChangedEvent] - vDaikinPower changed from OFF to ON
2019-08-01 14:59:44.774 [INFO ] [thome.model.script.DaikinPowerUpdate] - vDaikinPower=OFF
2019-08-01 14:59:44.786 [INFO ] [.smarthome.model.script.vDaikinPower] - vDaikinPower=ON
2019-08-01 14:59:44.809 [INFO ] [.smarthome.model.script.vDaikinPower] - acCommandString=http://192.168.100.9/skyfi/aircon/set_control_info?lpw=&stemp=22&shum=--&f_airside=0&f_dir=0&mode=0&f_auto=0&f_rate=1&pow=1&dt0=--
2019-08-01 14:59:44.929 [INFO ] [.smarthome.model.script.vDaikinPower] - sendHttpPostRequest() returns: ret=OK

I would expect to see 3 lines: HVAC item, Virtual item, Rule log note but it’s firing the virtual item rule once the HVAC item’s rule updates the virtual item. I’m also not sure why the loginfo command in the rule is showing the state as the opposite of what it just changed to. Does it only read the item state as the rule is entered into which is why it’s reporting as OFF immediately after the same rule has toggled it to ON?
I’ve taken out a bunch of the other lines but this is the items and rules file

// Parsed items
Number DaikinPower                                                          <switch>                {http="<[DaikinControlCache:1000:REGEX(.*,pow=(\\d),.*)]"}
// Virtual items
Switch vDaikinPower                                                         <switch>
var String acHost = "http://192.168.100.9/skyfi/"
var String acCommandString = ""
// virtual items changed
rule 'vDaikinPowerUpdate'
when
    Item vDaikinPower changed
then
    logInfo("vDaikinPower", "vDaikinPower=" + vDaikinPower.state);
    var String NEWSTATE
    if (vDaikinPower.state == ON) NEWSTATE="1" else NEWSTATE="0"
	acCommandString = "aircon/set_control_info?lpw=&stemp=" + (DaikinSetpoint.state as Number).intValue + "&shum=--&f_airside=0&f_dir=0&mode=" + DaikinMode.state + "&f_auto=0&f_rate=" + DaikinFan.state + "&pow=" + NEWSTATE + "&dt0=--"
    logInfo("vDaikinPower", "acCommandString=" + acHost + acCommandString)
    logInfo("vDaikinPower", "sendHttpPostRequest() returns: " + sendHttpPostRequest(acHost + acCommandString, 5000))
end      
// HVAC items changed
rule 'DaikinPowerUpdate'
when
    Item DaikinPower changed
then
        if (DaikinPower.state == "1") vDaikinPower.postUpdate(ON) else if (DaikinPower.state == "0") vDaikinPower.postUpdate(OFF)
		logInfo("DaikinPowerUpdate", "vDaikinPower=" + vDaikinPower.state)
end

Your rule triggers are for ‘changed’. They will fire for any state change, no matter what the source was. That’s the way they are designed to work.

openHAB is multithreaded, so things can and do happen in parallel.
Your rule DaikinPowerUpdate is triggered by a change in DaikinPower and issues an update to vDaikinPower. That goes onto OH event bus.

Meantime the rule goes on to display the state of vDaikinPower, which is still OFF.

A short time later, OH actions the update, generating the change to trigger the other rule.

This is all working as expected. Commonds and postUpdates are asynchronous, never wait before carrying on, never produce instant results.

That would make perfect sense to me if I were using .sendCommand as that states that it triggers further actions whereas .postUpdate doesn’t (well the table says depends for changed but doesn’t elaborate so that’s not overly helpful).
How would I design that rule so that it only fires once? It’s causing hiccups when multiple options are changed on the HVAC controller in short time as it then queues up requests that may revert the settings to a previous state (i.e. Press mode twice to go from fan > dry > cool, press power, press up/down n times to change set point. This might result in the controller showing what it’s intended state is, then rapidly changing to a different mode or temperature due to the queued multiple commands in OH).
As for my logs, I found this afterwards which sums it up " An important warning is worth mentioning here. When using the received command trigger, the Rule will trigger before the Item’s state is updated. Therefore, if the Rule needs to know what the command was, use the [implicit variable]receivedCommand instead of ItemName.state."

Okay, I’m not sure quite what you would expect from a rule triggered by ‘received update’ when we issue a postUpdate, but rest assured that it triggers and this is by design.
Likewise, a rule triggered by ‘changed’ triggers on every change.

So you need a rule to run in circumstance X, usually this can be done with careful choice of rule triggers and an appreciation of the sequence of events.
Sometimes it helps to break up a rule into a series of smaller rules, participating in a cascade of events.
It’s not particularly easy to get your head around programming with asynchronous events.

It’s not clear to me what any of your Items represent, there seems to be a target HVAC and some kind of remote, it’s not clear if that remote acts directly on the HVAC and reports to OH, or needs to act through OH rules, there is talk of polling something and sending OH commands to something.

Can you give us a step by step of your requirement?

  1. HTTP binding updates HVAC items regularly by polling HVAC controller. These are the items without a preceding v
  2. If anyone uses the HVAC controller and changes any parameters, the query received back from HTTP binding will update the HVAC items
  3. If the item value changes it should update the OH items. These are the items WITH a preceding v

A. OH items (with preceding v) are the ones referenced by HABPanel etc. so that there is no delay in waiting for a response from the HTTP binding before altering visible state to all users.
B. If any user changes a value from a panel then update the OH item for immediate reflection on all panels
C. Send HTTP request to HVAC controller to make the change to the system

C is currently reflected back automatically when HTTP binding polls the system next and receives the updated values. If I update the item state for the HVAC items too this would avoid the changed condition BUT when there are multiple commands queued it triggers them off again.

Basically the ruleset I have now is fine and updates from the controller/OH correctly, I just need it to not run when it’s changed via a rule to avoid spamming the controller.

Top of my head, it sounds like you want to be sending to HVAC only in response to OH Item commands from UI or rule.
Incoming updates don’t get into that flow.

Only problem with that is a ~1 sec delay after each button press, function change or temperature adjustment which feels yuck from a UI perspective, especially if you’re changing more than one thing at that time.

Okay, so where does that come from? I guess this is the wait for the next HTTP poll.

“B” in your previous description seems to deal with that, though? (Reads as the equivalent of OH inbuilt autoupdate)

Using a command (rather than a change) to a v-Item as a rule trigger would still allow you to pass that on as a HTTP command to HVAC (without updating the matching real-Item)…

Using a changed trigger on real-Item would still allow you to pick up on the next polled data, which hopefully shows a change in response to command, and issue an update to v-Item. v-Item is probably already in the correct state from your “B” action.

There is the potential glitch of a poll containing “old” data arriving at around the same time as you send a new command to the HVAC. This is always possible in any polled scheme.
But most likely the old data has not changed and so will not update the v-Item.

Workflow:
User presses UI button.
Maybe it’s a simple on/off
or
Maybe you need to do some calculation to work out new v-Item state.
Either way, a rule triggered by command to v-Item can;
Update v-Item
Send HTTP to HVAC
{leave the real-Item alone)

Later
HTTP poll updates real-Item
rule triggered by real-Item change updates v-Item

Yes that’s between polls which have additional delays due to POSTs when functions are run.

It does and that’s why I was using a OH only item to update instantly whilst the commands can just queue up but I didn’t take into account the updating from the HVAC controller queuing up and causing rapid changes.

That would be the case when it’s updated from OH but then I’m still in the same boat where v Item will be in the old state when the HVAC controller is used directly which means that it will trigger the HTTP POST when it updates the v Item from the HVAC item after a poll.

As it stands now from an OH perspective it works perfect, it’s the HVAC controller being used that causes the problems.

I don’t understand your issue here. My suggestion to trigger the rules that generate HVAC POSTs from v-Item commands will not do this.

Maybe it’s not clear that commands and state updates are distinctly different things within openHAB. UI use generates commands; incoming device data usually generates updates. Even when we’re using two Items loosely coupled by rules, the same general workflow can be maintained by choosing rule triggers and actions.

Example sketch

// UI user action
rule 'vDaikinPowerUpdate'
when
    Item vDaikinPower received command   // this is the item in UI, right?
then
    If not about to be done by autoupdate, update vDaikinPower (for snappy UI)
    POST HTTP to HVAC
    // leave the poll Item alone
end 
     
// HVAC items changed by poll
rule 'DaikinPowerUpdate'
when
    Item DaikinPower changed
then
     update vDaikinPower  // will not trigger other rule
end