Multiple commands to single item

I want to send multiple commands to single item in a rule. Unfortunetly only one command is received on the item.

basically in the rule is:

volume.sendCommand(DECREASE)
volume.sendCommand(DECREASE)

but in the log I can see that volume is changing its value only once. If sleep >500ms is added beetween those commands the volume is changed twice. Is this beaviour by the design or I am missing something ?

volume item is Dimmer type connected with mqtt bindig v1 (if this matters). OH version 2.5.0.

Why are you sending the command twice. Try to decrese the value directly to what you want. See my example below that reduces the volume with 5

Volume.sendCommand(volume.state - 5)

and what if the volume.state is already 0 ? what if the rule fires twice before volume state is updated ? This is not a good way to handle increasing/decreasing if there is already increase/decrese command that handles all of that.

Why are you sending multiple commands to same item in the same rule?

Volume is a percent type so 0 - 5 would be 0 same as 0 DECREASE

You can set the volume to whatever you want. 0 - 100

Volume.sendCommand(50)
// Volume.state = 50
Volume.sendCommand(Volume.state - 20)
// Volume.state = 30

This is not answering my question. My question is about OH behaviour in described case. I rephrase my question then. Does OH queue commands sent to the item ? Or only last command is handled by the item ?

Regarding proposed solution,
this: Volume.sendCommand(Volume.state - 20)
is NOT a good solution, this is classic race condition.

No. openHAB just rams its way through the DSL code, and won’t wait for an Item to have updated (more precisely: been commanded) before smashing the next message through!

Now, why are you sending the same command twice? :wink:

It does not matter now since the commands are not queued. If they were, then sending decrease comand twice instead of using current state to calculate new state would not cause reace condition.

@mczerski, I think people are asking what your larger goal is so that they can better understand what you’re trying to do and be helpful to you. That’s difficult without understanding your overall intentions.

I get that the initial comments didn’t directly answer your question (which can be frustrating), but shooting down friendly suggestions and declining to provide more context when people ask for it is not a great way to respond (particularly when you started the conversation).

There are a lot of times when someone asks a question not being aware of other possible solutions that might work better. We’re all just trying to be helpful to others in the community.

2 Likes

Sorry I must have misunderstood because I though a race condition was when you try and send 2 commands at the same time. Your rule and log show you have experienced a race condition.

You mentioned you were using old mqtt binding from you item to something.

The mqtt will not see the Decrease command just a state value.

It is unlikely Volume.sendCommand(Volume.state - 20) create a race condition in any case you can use a concurrency guard to protect you from a race condition.

This we can only help on the information you give and we sometimes assume things. You mentioning using a V1 MQTT means to me you have had your system up and running for a long time. You probably understand alot about how openHAB is structured.

Please explain what you are tying to do.
I hate posting this link

Ultimately this is an XY Problem. But in specific, a command is not the same as an update. When you send a command to an item, depending on a number of factors, it can take quite some time before the Item actually updates to a new state in response to the command. And that update occurs asynchronously.

So, when you issue two command without a delay between them, the Item hasn’t changed state in response to the first command when the second command is received. A DECREASE/INCREASE command is a relative command. It takes the current state of the item and adds/subtracts a fixed amount and the result of that is what becomes the command that goes to the binding and the device. Therefore, because the item hasn’t changed state yet, the second command is based on the Item’s state before the first command was sent and in the end the device gets sent the same number twice.

If you want to do this you either need the sleep.or, as has been suggested, calculate the result of the two commands in your rules and send that number as your command.

Here, by the race condition, what I mean is that:
Lets assume that the rule is triggered on some button item received an update. If I press the button twice very fast there is a possibility that the rule gets triggered twice BEFORE the volume state updates. Then from the volume item side I will see only one button press. And this I call a reace condition.
BUT, taking into account how OH works (thanks to the @hafniumzinc answer), this will happen even with DECREASE command since it will be received only once on the side of the item. So now I will not call that a race condition since the behaviour is by the design. And I just need to take it into account, and live with that I would miss some button presses in adge cases.

So it does not matter if I use DECREASE command or (volume.state - 5) command ? It is semantically the same ?

1 Like

I have remote with a button that send command A when pressed once and command B when pressed twice. Those two commands trigger a single rule that decreases some dimmer item which reflects volume. I want to assure that every single press will cause volume to go down one step.

Cool

You can use an implicant variable. recievedCommand so you can do something cool like if command A drop volume by 1 step or else if B drop it by 5 steps.

Because it is a closed loop system any race condition will be quicly noticed and corrected by the user.

You can also use lastupdate to detect fast succetion pushes and change the step size.

I did some tests and It DOES matter if I send DECREASE or PercentType command to the volume item.
First of all, DECREASE/INCREASE commands are sent to the binding, so they are interpreted on the bindig side. So sending DECREASE to my volume item which is connected to mqtt bindig actually sends the DECREASE command to mqtt bindig (where I can interpret that command with transformation script, at least in mqtt v1).

Second, using sendCommand(volume.state - 5) does not work, what might work is:
sendCommand((volume.state as Number - 5))
but that does not work when volume.state is less than 5, I get error:

Cannot convert ‘-5’ to a command type which item ‘volume’ accepts: [PercentType, OnOffType, IncreaseDecreaseType, RefreshType].

trying with:
sendCommand(new PercentType((volume.state as Number) - 5))
couses an error to:

Value must be between 0 and 100

Third, I would need to hardcode the step value in a rule file (I believe that there is no way to share some code beetween rules files). Using DECREASE command I can define the step in the tranformation script or even on the end device receiveing the mqtt message.

So thats why using DECREASE command twice in a rule would be a better solution (if it would work of course).

Correct, assuming the decrease subtracts five. But again, if you send that command twice without a delay you’ll get the same situation because the Item doesn’t immediately change state in commands.

You would have to handle that yourself in the rule. A PercentType cannot be a negative number or greater than 100. you have to prevent that in your rule if you send the command as a number instead of increase/decrease.

It depends. There are lots of techniques to achieve this with .rules files. It’s easy to do with Jython, JavaScript, and Groovy rules.