Using state of Player Item in if-function

Hi everyone,

I am running OH 3.0.1 and I have some issues working with player items. (New rule, so I dont know if it would have been working on 2.5)

I have created two Player Items.
Player DenonPlayerViaHarmony is not linked to a channel and can be commanded by a sitemap
Player HarmonyPlayer is linked to my harmony binding and sends the commands to the device

I want to define a rule, where the command in DenonPlayerViaHarmony is only pushed to HarmonyPlayer if another Switch item is turned on (this exceptions isn’t implemented in the following code for debugging reasons - so the code should only push new commands for DenonPlayerViaHarmony to HarmonyPlayer.

Any attempts of doing so like

HarmonyPlayer.sendCommand(DenonPlayerViaHarmony.state)

does not work and causes the following error in log

==> /var/log/openhab/openhab.log <==
2021-03-25 07:53:06.871 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'harmony-1' failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.actions.BusEvent.sendCommand(org.openhab.core.items.Item,java.lang.String) on instance: null in harmony

In my next attempt, I want to identify the state by an if function and then, send the specific command

rule "Denon Steuerung Widergabe"
when Item DenonPlayerViaHarmony received command
then
    if(DenonPlayerViaHarmony.state == PLAY)
    {
    HarmonyPlayer.sendCommand(PLAY)
    }
    if (DenonPlayerViaHarmony.state == PAUSE)
    {
    HarmonyPlayer.sendCommand(PAUSE)
    }
    if (DenonPlayerViaHarmony.state == NEXT)
    {
    HarmonyPlayer.sendCommand(NEXT)
    }
    if (DenonPlayerViaHarmony.state == PREVIOUS)
    {
    HarmonyPlayer.sendCommand(PREVIOUS)
    }
    if (DenonPlayerViaHarmony.state == FASTFORWARD)
    {
    HarmonyPlayer.sendCommand(FASTFORWARD)
    }
    if (DenonPlayerViaHarmony.state == REWIND)
    {
    HarmonyPlayer.sendCommand(REWIND)
    }
end

This rule does work for PAUSE and PLAY state. But for no known reason, NEXT and PREVIOUS are triggering the rule but just sending the last command.

So if I set DenonPlayerViaHarmony to PLAY, HarmonyPlayer is set to PLAY accordingly
If I now set DenonPlayerViaHarmony to NEXT, Harmony Player is set to PLAY again. also with more attempts.

If I now set DenonPlayerViaHarmony to PAUSE, HarmonyPlayer is set to PAUSEaccordingly
If I now set DenonPlayerViaHarmony to NEXT, Harmony Player is set to PAUSE again.

==> /var/log/openhab/events.log <==
2021-03-25 08:20:31.497 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'DenonPlayerViaHarmony' received command NEXT
2021-03-25 08:20:31.512 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'HarmonyPlayer' received command PLAY
2021-03-25 08:20:31.516 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'HarmonyPlayer' predicted to become PLAY

Something has to be wrong in the if-function.
To solve it, I allready tried a conversion to String like this:

    if(DenonPlayerViaHarmony.state.toString() == "PLAY")
    {
    HarmonyPlayer.sendCommand(PLAY)
    }
    if (DenonPlayerViaHarmony.state.toString() == "PAUSE")
    {
    HarmonyPlayer.sendCommand(PAUSE)
    }
    if (DenonPlayerViaHarmony.state.toString() == "NEXT")
    {
    HarmonyPlayer.sendCommand(NEXT)
    }

Play and Pause do work again. Nest triggers again the last event.

Is this related to the differend types, stored in a Player Item? Like “PlayPauseType”, “RewindFastforwardType” etc? so by this, the .state only extracts the PlayPauseType? For what I know, there isnt any conversion like “.toPlayPauseType”.

What can I do to solve this?

Thanks in advance,

Tamo

I think it may be the sendCommand(). Item states are not commands, even if they look the the same.
Try
someSwitch.sendCommand(otherSwitch.state)
to discover state ON is not command ON.
The trick is to send it as a string so that the Item is forced to parse it into exact object it wants.
someSwitch.sendCommand(otherSwitch.state.toString)
I would treat your rule like this, and see what problems remain after.

You’d probably want to restructure your rule as if() - else if() really, for greater efficiency.
A popular shorthand way to do that tat is with a switch-case construct.
You’d avoid any unexpected horrors should the state change partway through that way.

2 Likes

Hi rossko,

the sending part works fine. But I tried another way:

with

TestString.postUpdate(DenonPlayerViaHarmony.state.toString())

I am extracting the state of the player Item to a String Item which I can then display in a Sitemap.

For PLAY, the TestStrings Value changes to PLAY
For PAUSE, it changes to Pause. For the other actions, it doenst change.

To me it seems, like .state.toString() of a PLAYER item extracts the state of the PlayPauseType Content of this string. When clicking on Fast Forward, the player item gets an update so the rule is executed. But the Content of the PlayPauseType still stays the same… Now the big question: Is it possible to extract the full types of the player item so that the Text changes to “Fast Forward” or “Rewind”…?

Regards

Tamo

I still don’t know how to extract the different types. But like this, it is working:

The commented sections are an alternative to use harmony command instead of direct SSH-Control of the receiver.

rule "Denon Steuerung Widergabe"
when Item DenonPlayerViaHarmony received command
then
    switch(receivedCommand) {
        case PLAY: {
            DenonCommand.sendCommand("NS94")
            //HarmonyDenon.sendCommand("Enter")
        }
        case PAUSE: {
            DenonCommand.sendCommand("NS94")
            //HarmonyDenon.sendCommand("Enter")
        }
        case NEXT: {
            DenonCommand.sendCommand("NS91")
            //HarmonyDenon.sendCommand("DirectionDown")
        }
        case PREVIOUS:{
            DenonCommand.sendCommand("NS90")
            //HarmonyDenon.sendCommand("DirectionUp")
        }
    }
end

Maybe we should review what to expect here.
Clicking on UI sends commands to Item.
This does not directly affect Item state.
In general the command gets passed via binding to real device.
Later the device may report a new status to binding, which in turn updates the Item state.

A major influence on this basic workflow is openHABs autoupdate feature. This is enabled for each Item by default (but may be disabled).
This listens for commands, like a binding, and makes educated guesses about the likely outcome. These predictions are applied to the Item state. The idea is to pre-empt the real device response quickly, and avoid noticeable lag at the UI. Afterwards we may get a real update of course.

Autoupdate is also very useful when you have a proxy/dummy/unlinked Item, making it appear to respond to commands. But we need to remember it’s making educated guesses, and not blindly copying command to state.

In the case of a Player type Item, we can send commands
PLAY PAUSE NEXT PREVIOUS REWIND FASTFORWARD.

Send PLAY or PAUSE produces a simple prediction, state will unsurprisingly become PLAY or PAUSE.

But Autoupdate predictions do depend on current state.
If the state is PAUSE, commanding NEXT PREVIOUS REWIND FASFORWARD has no effect. The prediction is “It’s paused,nothing happens”.
If the state is PLAY, commanding REWIND FASTFORWARD will now produce state REWIND or FASTFORWARD
If the state is PLAY, commanding NEXT PREVIOUS has no affect. The prediction is “skipped a track, still playing”

If you want to act on UI sent commands in your rule,use the sent command in the form of the receivedCommand implicit variable.
Do not expect state to reflect those.

I should have picked this up earlier for you, because you are also facing a race condition. If you trigger off command and immediately examine state, autoupdate may or may not have acted yet (if its going to act at all) so your results are indeterminately “before” or “after” .