Heos (Denon) support

That’s where you’ve gone wrong then.

Allow PaperUI to add the New Thing, so that you can see what the lovely new features are.

AKA

“How can you possibly create the correctly formatted Thing (text) file, if you don’t know what to add?”

For example

{
  "statusInfo": {
    "status": "ONLINE",
    "statusDetail": "NONE"
  },
  "editable": true,
  "label": "Lounge-AV-Amp HEOS",
  "bridgeUID": "heos:bridge:07c42678-e5e2-1ce8-0080-0005cde91312",
  "configuration": {
    "pid": "368816113"
  },
  "properties": {
    "IP Address": "192.168.1.50",
    "serialNumber": "AUYxxxxxxxxxx",
    "modelId": "Denon AVR-X4400H",
    "vendor": "Denon",
    "Connection": "wired",
    "pid": "368816113",
    "firmwareVersion": "1.562.281",
    "Name": "Lounge-AV-Amp"
  },
  "UID": "heos:player:368816113",
  "thingTypeUID": "heos:player",
  "channels": [
    {
      "linkedItems": [
        "HeosPlayerLoungeAVAmp_Control"
      ],
      "uid": "heos:player:368816113:Control",
      "id": "Control",
      "channelTypeUID": "system:media-control",
      "itemType": "Player",
      "kind": "STATE",
      "label": "Media Control",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:Volume",
      "id": "Volume",
      "channelTypeUID": "system:volume",
      "itemType": "Dimmer",
      "kind": "STATE",
      "label": "Volume",
      "description": "Change the sound volume of a device",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:Mute",
      "id": "Mute",
      "channelTypeUID": "system:mute",
      "itemType": "Switch",
      "kind": "STATE",
      "label": "Mute",
      "description": "Mute audio of the device",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:Inputs",
      "id": "Inputs",
      "channelTypeUID": "heos:input",
      "itemType": "String",
      "kind": "STATE",
      "label": "External Inputs",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "HeosPlayerLoungeAVAmp_Song"
      ],
      "uid": "heos:player:368816113:Title",
      "id": "Title",
      "channelTypeUID": "system:media-title",
      "itemType": "String",
      "kind": "STATE",
      "label": "Media Title",
      "description": "Title of a (played) media file",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_MediaArtist"
      ],
      "uid": "heos:player:368816113:Artist",
      "id": "Artist",
      "channelTypeUID": "system:media-artist",
      "itemType": "String",
      "kind": "STATE",
      "label": "Media Artist",
      "description": "Artist of a (played) media file",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "HeosPlayerLoungeAVAmp_Album"
      ],
      "uid": "heos:player:368816113:Album",
      "id": "Album",
      "channelTypeUID": "heos:album",
      "itemType": "String",
      "kind": "STATE",
      "label": "Album",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_Cover"
      ],
      "uid": "heos:player:368816113:Cover",
      "id": "Cover",
      "channelTypeUID": "heos:cover",
      "itemType": "Image",
      "kind": "STATE",
      "label": "Cover",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_TrackPosition"
      ],
      "uid": "heos:player:368816113:CurrentPosition",
      "id": "CurrentPosition",
      "channelTypeUID": "heos:currentPosition",
      "itemType": "Number:Time",
      "kind": "STATE",
      "label": "Track Position",
      "description": "The current track position",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_TrackDuration"
      ],
      "uid": "heos:player:368816113:Duration",
      "id": "Duration",
      "channelTypeUID": "heos:duration",
      "itemType": "Number:Time",
      "kind": "STATE",
      "label": "Track Duration",
      "description": "The overall duration of the track",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_Type"
      ],
      "uid": "heos:player:368816113:Type",
      "id": "Type",
      "channelTypeUID": "heos:type",
      "itemType": "String",
      "kind": "STATE",
      "label": "Type",
      "description": "The media currently played type (station, song, ...)",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "HeosPlayerLoungeAVAmp_TheStationName"
      ],
      "uid": "heos:player:368816113:Station",
      "id": "Station",
      "channelTypeUID": "heos:station",
      "itemType": "String",
      "kind": "STATE",
      "label": "Station",
      "description": "The name of the station currently played",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_PlayURL"
      ],
      "uid": "heos:player:368816113:PlayUrl",
      "id": "PlayUrl",
      "channelTypeUID": "heos:playUrl",
      "itemType": "String",
      "kind": "STATE",
      "label": "Play URL",
      "description": "Plays a media file from URL",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:Shuffle",
      "id": "Shuffle",
      "channelTypeUID": "heos:shuffleMode",
      "itemType": "Switch",
      "kind": "STATE",
      "label": "Shuffle",
      "description": "Sets the shuffle mode",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:RepeatMode",
      "id": "RepeatMode",
      "channelTypeUID": "heos:repeatMode",
      "itemType": "String",
      "kind": "STATE",
      "label": "Repeat Mode",
      "description": "Set the repeat mode",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_Favorites"
      ],
      "uid": "heos:player:368816113:Favorites",
      "id": "Favorites",
      "channelTypeUID": "heos:favorites",
      "itemType": "String",
      "kind": "STATE",
      "label": "Favorites",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [
        "LoungeAVAmpHEOS_Playlists"
      ],
      "uid": "heos:player:368816113:Playlists",
      "id": "Playlists",
      "channelTypeUID": "heos:playlists",
      "itemType": "String",
      "kind": "STATE",
      "label": "Playlists",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:Queue",
      "id": "Queue",
      "channelTypeUID": "heos:queue",
      "itemType": "String",
      "kind": "STATE",
      "label": "Queue",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    },
    {
      "linkedItems": [],
      "uid": "heos:player:368816113:ClearQueue",
      "id": "ClearQueue",
      "channelTypeUID": "heos:clearQueue",
      "itemType": "Switch",
      "kind": "STATE",
      "label": "Clear Queue",
      "defaultTags": [],
      "properties": {},
      "configuration": {}
    }
  ],
  "location": "Lounge"
}

It would be nice if we could use the _control item to start and stop the player with ON and OFF.
The readme said it should work this way:

Control	Player	Play (also ON) / Pause (also OFF) / Next / Previous

It works for me with Play and Pause, but not with ON and OFF.

I am in the process of switching from squeezebox to HEOS. I have KNX Wall-Switches and used them to
switch off all lights and the squeezeboxes when i left a room. I could do this without any rules just with the items. I understand that the HEOS Boxes are not really powered off, but it would be nice to have an OFF Command to Pause the box.

I haven’t read the full thread and likely do not have all the details to answer. But perhaps the following will shed some light on the situation.

When you perform any action on the sitemap it results in a command. So of course, when you select a playlist on the sitemap, it is going to become a command that goes out to start playing that playlist.

If I understand correctly, you want to select a playlist that will play later based on some event (alarm). So you need an Item on the sitemap that is not linked to the device which lets you select the playlist. Since this Item is not linked to a device, nothing will happen when you select a playlist from the sitemap.

Something you’ll have to figure out is how to populate that playlist with the selection. That’s not something I’ve ever tried. Next you will have a rule triggered on your alarm event. Finally, that rule will send the current state of the Alarm Playlist Item to the Item actually linked to the device as command.

2 Likes

thanks for your reply!

Me neither and I fear that that might troublesome, I thought along the way of a second item and trying things with auto-update and profiles but I think that neither of those will work. The main thing it should do is populate the item but not forward commands.

That should be rather straight forward I’ll try to look into the support for ON / OFF this week!

Oh I get it now…

I’ve got something similar going on with a ChromeCast audio device in our bathroom.

The logic being

When the shower flow gets hot, query the playlist / station choice Item and play the relevant stream.

I think I have about 10 options to choose from. (I have even got a schedule setup to avoid certain stations at certain times / days, but that’s a different subject.

So here’s how I’ve done it.

I have a orphan number item that stores my choice.

In HabPanel I have a selection widget with a comma separated list, linked to the Orphan number Item

something like

1=Radio 1,2=BBC Radio 2,3=Absolute radio

and so on

When the shower water flow gets hot, it triggers a rule, which I guess could be a switch case arrangement or a Node-RED flow. Whatever you are more comfortable with.

I’m a beginner in programming, so my pair of rules look something like this

rule "Radio choice"
when
Item ShowerTemp changed to ON
then
if (ShowerRadioChoice.state == 1) { 
ShowerFavorite.sendCommand("BBC Radio 1")
}
if (ShowerRadioChoice.state == 2) { 
ShowerFavorite.sendCommand("BBC Radio 2")
}

if (ShowerRadioChoice.state == 3) { 
ShowerFavorite.sendCommand("Absolute Radio")
}
else
{
ShowerFavorite.sendCommand("Planet Rock")
}

end

rule "Shower Radio OFF"
when
Item ShowerTemp changed to OFF
then
ShowerMusicPlayer.sendCommand("STOP") // it actually does something far cooler than just stop, but again, that's for a different thread
end

In the interest in learning:

In the original code, don’t forget about else if.

if (ShowerRadioChoice == 1) { 
    ShowerFavorite.sendCommand("BBC Radio 1")
}
else if (ShowerRadioChoice == 2) { 
    ShowerFavorite.sendCommand("BBC Radio 2")
}

As a switch statement:

rule "Shower Radio ON"
when
    Item ShowerTemp changed to ON
then
    // Indentation is important to help the person reading the code understand the what lines correspond with what context.

    // Let's put the command at the end so, if in the future you want to do other stuff before sending 
    // the command you only have to do it once. So first record a default:
    var choice = "Planet Rock"

    // A switch statement is often more concise in this sort of if/else statements
    switch(ShowerRadioChoice.state as Number) { // I assume ShowerRadioChoice is an Item?
        case 1: choice = "BBC Radio 1"
        case 2: choice = "BBC Radio 2"
        case 3: choice = "Absolute Radio"
    } 

    ShowerFavorite.sendCommand(choice)
end

As a lookup using a Map:

import java.util.Map

val Map<String, String> stations = newHashMap("1" -> "BBC Radio1",
                                              "2" -> "BBC Radio 2",
                                              "3" -> "Absolute Radio")
rule "Shower Radio ON"
when
    Item ShowerTemp changed to ON
then    
    var choice = stations.get(ShowerRadioChoice.state.toString())
    if(choice == null) choice = "Planet Rock"
    ShowerFavorite.sendCommand(choice)
end

As a lookup using a List:

import java.util.List

val List<String> stations = newArrayList("BBC Radio1", "BBC Radio 2", "Absolute Radio")

rule "Shower Radio ON"
when
    Item ShowerTemp changed to ON
then
    val index = ShowerRadioChoice.state as Number
    var choice = "Planet Rock"
    if(index > 0 && index < stations.size) choice = stations.get(index.intValue)
    ShowerFavorite.sendCommand(choice)
end
1 Like

I have no idea how you work such magic. :mage:

My favourite of those would be the map, the small part of my brain that is reserved for programming can see how that is structured.

Thank you once again for bringing your knowledge to the party.

@Anne11e I was too quick this is not allowed by the framework :frowning:

The code is there in the HEOS binding but the openHAB framework does not forward the ON/OFF.

It seems that if your knx things would be of the type system.rawrocker you could use a profile but most likely the knx binding has to changed for that :frowning:. I must admit that my profile knowledge is minimal but looking at this it could even make sense to add another profile but I’m not sure about it maybe @cweitkamp could tell us more about the profiles.

The profile which could help us is system:rawrocker-to-play-pause and can be seen in action in the README of the EnOcean binding.

The alternative would be to have some rules to do this.

FYI, and for completeness, in OH3 - so disregard this for now if you’re not using it - state & command options, when not provided by the link/binding, you’re able to configure them (or override if they are) with metadata on the item.

So if you have an item for the radio station and say its valid options are 1, 2, or 3:

You can specify these options in the stateDescription metadata namespace, using:

  • the UI
  • text files (for static options)
  • eventually, rules or other means (for dynamic options) - remember you can have an item defined using an .items file but have a metadata namespace for it in the JSONDB.

In the UI you would click on “State Description” under “Metadata” and provide the options in the text area:

The equivalent in an .items file would be:

String RadioStation "Radio Station" { stateDescription=" " [ options="1=BBC Radio 1,2=BBC Radio 2,3=Absolute Radio" ] }

The default widget for the item will now display the label of the corresponding option instead of the actual state. Moreover, if the item isn’t read only, the control becomes clickable and allows to select another option - sent as a command. Those are actually command options - but by default they are conveniently set to be the same as the state options. If they differ they’re configurable with the commandDescription namespace in the same manner.

3 Likes

thanks for your research. i tried the profile in my channel but this didn’t work, like you expected.
I have now created some rules for the ON/OFF

You can find everything about profiles here. If I understand you correctly you are looking for a way to convert / map OnOffType to PlayPauseType? AFAIR currently there is no way to do so other than a rule - even it is not that hard to archive. A profile sounds reasonable but before starting to code I would like to point to this feature request which could be a start or an approach to solve this issue.

Hello @PhilippRoessner and others,

I took a dive into profiles today and managed to create a profile that can be added to the playlist items and can be used to tune the action which is performed on sending a command. For @PhilippRoessner the action which would be most relevant is IGNORE.

We briefly discussed some modeling in an other topic.

My local changes give the following possible item definitions for playlists

String        KantoorHEOS3_Playlists         "Playlists normal, triggers PLAY_NOW"         {channel="heos:player:-831584083:Playlists"}
String        KantoorHEOS3_Playlists_t_1         "Playlists normal, triggers PLAY_NOW"   {channel="heos:player:-831584083:Playlists" [profile="heos:play"]}
String        KantoorHEOS3_Playlists_t_2         "Playlists triggers given action"   {channel="heos:player:-831584083:Playlists" [profile="heos:play", action="PLAY_NOW"]}
String        KantoorHEOS3_Playlists_t_3         "Playlists triggers given action"   {channel="heos:player:-831584083:Playlists" [profile="heos:play", action="IGNORE"]}
String        KantoorHEOS3_Playlists_t_4         "Playlists triggers given action"   {channel="heos:player:-831584083:Playlists" [profile="heos:play", action="REPLACE_AND_PLAY"]}
String        KantoorHEOS3_Playlists_t_5         "Playlists triggers given action"   {channel="heos:player:-831584083:Playlists" [profile="heos:play", action="ADD_TO_END"]}
String        KantoorHEOS3_Playlists_t_6         "Playlists triggers given action"   {channel="heos:player:-831584083:Playlists" [profile="heos:play", action="PLAY_NEXT"]}

CC: @rkrisi, @Wire82

Is this something that makes sense for all of you? Or would it make more sense to have different channels for different actions? Any suggestions from you?

Thanks a lot!

Hi, I have a bunch of Heos devices in my house to use the multiroom functions.
I wanted to use openhab an some presence sensors to give the multiroom functionality some more intelligence. But I have several issues with the group functionality:

  • Sometimes the bindings tells that multiple groups are activated which is not the case, it seems to mix up the groups if there are similar speakers playing. E.g. when I turn on the office/living room/kitchen group also the office/living room group is turned on. But also sometimes the groups don’t match at all, e.g. when the office and kitchen are currently playing also the group office/living room is sometimes turned on, which doesn’t make any sense.
  • The bigger issue is, that it seems to mix up master and slaves. E.g. sometimes the office shall be the master and living room just the slave, and sometimes otherwise. Unfortunately, when I’ve created the office/living room group the living room/office group never shows up in the inbox when turned on.

I’ll now switch temporarily to a heos cli solution, until this is also working fine in openhab. Please let me know if I can assist you guys in anyway to get this solved or maybe even improve it, as the group/switch-logic gets quite complex when you have some more devices and constellations. :wink:

In the binding there was a deliberate choice made that two groups which have the same members are treated as the same group, without making the distinction who is master and who is the slave. The fact that groups are turned on randomly is of course not intended behavior.

Does the fact that it treats those groups as the same already explain part of the behavior you see? What issue does that cause for you?

Yes it explains part of the bevahior. The issue that I have with that is, that I want to use openhab to turn groups off an on. E.g. when I’m listening in the office and move to the living room I switch on the office/living room group. That’s fine when the music is currently playing in the office. But if it’s the other way, I’m in the living room, listening to music there and move now to the office, turning on this exact group will set the office as the master and directly stop the playback in the living room, as obviously nothing is playing on the office. Therefore in this case the living room has to be the master.

@Wire82 do you recall why this approach was chose. What do you think is the most sensible to do? Should we rewrite the grouping such that two groups with the same members are the same depending on who is the master? Do you think that that could combine the best of two worlds?

Thanks a lot for your time and efforts!

@airbone42 & @martinvw
The reason for the current behavior is that the binding does not know, which player is currently playing music and taking this as a master for the group. Normally the group is build in the same arrangement like it was created the last time. So for example if it was player 1,2,3 (1 is the master then) it will be a group with the arrangement 1,2,3 for the next time the group is generated if you are using the grouping switch of the group. If you, for some reason, making a group with the listing 2,3,1 player 2 will be master and the binding is updating the arrangement. So if you are building the group the next time via OpenHAB it will be 2,3,1.
An idea is to use a rule within OpenHAB, to generate the group via the bridge. Then the rule could check which player of the group is currently playing and using this as a master. This works if our are using the player channels at the bridge. The first player you select, will be the master and will take over the currently played music for the group.
The other idea is, that this could be also added as a rule to the binding as included function.
I choose this behavior, because for me it was important, that a group is identified as the same group every time it is build, independent from the player sorting within the group. So a 1,2,3 group should be the same as 2,3,1 and 3,1,2 for example.
Does the answer helps a bit?

1 Like

I have been struggling with group functionality recently as well. For my example, let’s say I have players 1, 2, 3, 4. For this example, player 1 is always the master, and I want 3 distinct groups: (1,2), (1,2,3), (1,2,3,4). I create these groups in the UI. I can create the first group (1,2) and all is well. When I create the second group (1,2,3), all the group properties (“members”, “Members Hash value”, etc) in group 1 are over-written to match the properties of the group 2. When I create the third group (1,2,3,4), all the properties in group 1 and group 2 are overwritten with the properties of group 3. I am left with three groups that are essentially the same. When I turn one group on or off, the other two groups turn on or off at the same time. They are not distinct.

I understand that the GID for all these groups will be the same since they all have the same master player, but I’m looking for the ability to distinguish between the 3 configurations of the group so I can illuminate some local keypads to give a visual indication if that room’s player is part of the group or in local mode. If the “member” or “Members Hash value” was not overwritten, I might have a way to distinguish these configurations. Is this possible?

I will take a look at it this evening it should not be to hard to fix that part of the problem. It seems like the same issue which was also reported by @airbone42