Update state of channel without updating device (Amazon Echo Control volume)


I am trying to solve the following issue: for my Sonos devices I have two things each, one via the Sonos binding and one via the Amazon Echo Control binding, the latter for issuing voice notifications via Alexa.

However there seems to be an issue with the volume channel from the Echo binding, it does not get updated when the volume is changed via the Sonos app (or the Sonos binding or on the device). Changing the volume via the Echo binding works, but it takes quite a long time for the Sonos to change the volume, 5-10 seconds.

Unfortunately having the volume set correctly in the Echo thing is important, because if music is played and then an Alexa command is issued, the volume afterwards is set to that of the Echo thing by the binding.

My first thought was an Item that links the two channels, the Sonos with follow-profile and the Echo with default-profile:

However, there is two issues with that. First, it does not work, for some reason the Item does not get updated if the Sonos volume changes, not sure why. But even if it would work, I think I’d run into another problem, because the update of the Echo channel would send an update to the device, with a delay, and that would likely interfere with the volume setting via other means.

So, ideally, I’d be looking for a way to update the volume only in the Echo thing/binding, but not have it send a command to the device.

Any ideas/suggestions on how to achieve that?

Try a rule when Sonos volume is changed postUpdate to the echo volume.
It updates the item without sending a command

But it would then only update the item without sending anything to the thing/channel, right? Without having tried it, this is most likely not going to solve my issue. Because I need the thing/binding to get the updated volume, because probably that is where it takes the volume from when it resets the volume after the Alexa announcement via the speak channel. The speak channel is probably not accessing the item for that, or would it?

I don’t know what volume will the speak channel use.
Maybe you can send a ‘speak with this volume’ command?
what is with a rule that send a command to the echo channel if Sonos volume doesn’t changed for some seconds… :man_shrugging:t3:
Or, if sending a voice notification send a volume before…

Yes, there is a separate channel for speak volume, but the issue is about the volume the music is then set to when it is resumed afterwards. It is set to the value the volume channel of the Echo binding has, that is why I need it to get updated.

Yes, the first one I also thought about, with a timer that gets reset when the volume changes and then updates the Echo channel. A bit of an effort but doable and could also be done in a generic rule that is applied for multiple devices.

That is how I am doing it right now, what I don’t like about it is that I cannot use group commands anymore.

Basically I am looking for the most easy-to-maintain solution for when I later use these notifications in many different places and/or have to add or remove devices.

Doing it via an Item that binds the two channels together would have solved it most elegantly, without any impact on further usage of the feature, but that did not work. Any solution that needs scripting will require some reference to the involved items. But with a naming convention applied to all devices and putting the necessary logic into a reusable JS function it will probably work out just fine.

Or, put a rule in place for each device, triggered by the speak command, and set the volume there. Since the processing of the speak command takes some time, the volume update would most likely be done in time, but I’d have to test that. Advantage would be that I can then use the speak command elsewhere without scripting.

I think the easiest way is to send the Sonos volume to the echo at a change. So your are always in sync.

Yes, but I’d still need that timer there, to avoid that the update to the Echo overwrites any later changes done from the Sonos. For some reason there is a noticeable lag when changing the volume via the Echo binding, a couple of seconds at least, so there is a real risk of interference I think. Also I’d need to avoid any endless loops of the two items/things updating each other. All in all this cries out for some racing condition to mess things up.

I would something do like:

If Sonos volume changed

If Timer runs reschedule Timer
start timer
at end of timer
set echo volume to Sonos volume value

I think this is ok.

I opted for the simpe approach of setting the volume when the speak command is issued, with a rule that is triggered by the speak command. The script is much simpler because it does not need a timer, and I assume the risk of interference is lower, simply because it is unlikely that somebody is changing volume just at the same time a voice announcement is played.

New devices just have to be added to the rule and need to comply to the naming convention for the points, otherwise I can just use the speak command anywhere in my other scripts and rules, without having to care about this issue. This will also make it easy to remove the workaround in case the issue gets fixed in a future release.

Here is the rule and script:

 * For Echo Control things/items for Sonos devices, the volume does not get
 * properly updated when the volume is changed via the Sonos app, on the device
 * or any other means.
 * This is an issue when playing a voice command, because after that the volume
 * of the music played gets set to the volume of the Echo Control thing.
 * This rule therefore aligns the Echo Control volume with the Sonos
 * before a voice command is issued, and also set the volume for the voice command.
var nameSeparator = "_";
var sonosVolumeNamePrefix = "Sonos_";
var sonosVolumeNameSuffix = "_Volume";
var echoVolumeNamePrefix = "Echo_Control_Sonos_";
var echoVolumeNameSuffix = "_Volume";
var echoSpeakVolumeNamePrefix = "Echo_Control_Sonos_";
var echoSpeakVolumeNameSuffix = "_Speak_Volume";

// Parse the name and get items as per the naming convention
var speakName = event.itemName;
var room = speakName.split( nameSeparator )[3];
var sonosVolume = items.getItem( sonosVolumeNamePrefix + room + sonosVolumeNameSuffix );
var echoVolume = items.getItem( echoVolumeNamePrefix + room + echoVolumeNameSuffix );
var echoSpeakVolume = items.getItem( echoSpeakVolumeNamePrefix + room + echoSpeakVolumeNameSuffix );

var logMsg = "Echo Volume: '" + sonosVolume.name + "'=" + sonosVolume.state + ", '" + echoVolume.name + "'=" + echoVolume.state + ", '" + echoSpeakVolume.name + "'=" + echoSpeakVolume.state;

// Set the volumes
if( echoVolume.state != sonosVolume.state )
    logMsg += ", setting Echo volume to " + sonosVolume.state;

    echoVolume.sendCommand( sonosVolume.state );

if( echoSpeakVolume.state != sonosVolume.state )
    logMsg += ", setting Echo speak volume to " + sonosVolume.state;

    echoSpeakVolume.sendCommand( sonosVolume.state );

console.debug( logMsg );