ebaauw / homebridge-zp

Homebridge plugin for Sonos ZonePlayer
Apache License 2.0
243 stars 20 forks source link

Enhancement: Only allow TV input in supported rooms #206

Open rfiorentino1 opened 1 year ago

rfiorentino1 commented 1 year ago

Issue

Unlike other input/audio sources connect to Sonos through amps etc, currently Sonos only allows you to select the TV source in a room where there is an arc or amp with an HDMI/TV connected directly to it. I confirmed this with Sonos support today too, because I thought I was missing something. ZP doesn't currently understand this logic; more info/example below.

I have 4 sonos amps, and a few Ones etc. I only have one TV connected to Sonos, in the living room. If I choose Living Room in the sonos app, and then select TV from the browse tab, all is well.

However, because I have amps in 3 other rooms, I have the option to choose TV in the Kitchen, back porch, etc. But doing this in the sonos app causes the "connection issue, let's fix it!" error to appear.

The side effect of this with ZP is the following:

Is there any way to tell where a TV is connected, and only allow that room to switch to the TV input? (e.g. if Kitchen doesn't have a tv, skip over it's input when changing inputs and go to the next input/favorite). Please let me know if any of this needs clarification, as it's a little tricky to explain in writing. Unfortunately the log messages for the inputs have disappeared already, but I can try and replicate tomorrow if needed.

ebaauw commented 1 year ago

The TV input is visible only for zones that have a master zone player with TV input, or are grouped with a zone that has one. Same for Line In and AirPlay. Check the accessory setting in Home to see the inputs, and enable or disable these.

When there are no valid input sources, indeed Homebridge ZP will loop on changing the input, until it reports an error. Originally I had added the Sonos Chime, to always have at least one valid input, but people didn’t like that, so that’s disabled by default.

rfiorentino1 commented 1 year ago

Hmmm, that doesn't seem to be the case for me. Is each item in the favorites list also considered a valid input? If so, ZP should never go into a loop for me because I always have things in that list. Also, ZP does seem to think there is a valid TV accessory in every room, possibly because I can also still choose that as an input for every room in the Sonos app, even though it errors out. This is not the case with any other line in or airplay etc, where it's not actually an option to begin with in rooms that it doesn't exist in. I'm not sure how this applies to the information that ZP is receiving from players etc but wondering if that has something to do with it. The TV source seems to be an outlier in the way that Sonos deals with it, and I didn't realize that until yesterday

I will replicate this later today and Post logs as well, but trying to figure out the above logic first

rfiorentino1 commented 1 year ago

Here are the relevant logs. Logs of input changes start at 11:20, but I wanted to include the others here as well, because they've brought up a few more questions:

(it wouldn't let me paste the log here because it was too long πŸ˜‚ so I've attached it below:

ZP log 06-20-2023.log

ebaauw commented 1 year ago

Is it normal that each room is assigned all of those 96 inputs, and then a few of them are renamed to their respective source? I'm assuming yes, just never noticed it before.

Yes. HomeKit doesn't like configuration changes, so I create all (possible 96) input services on startup. They're marked unconfigured, so Home doesn't show them. Next, the valid services are configured and renamed. Input 1 is for grouping/ungrouping, 2 for Airplay, 3 for Audio In, 4 for TV, the next for Sonos Favourites, and the last for the Sonos Chime. Set maxFavourites in config.json to limit the number of input services (I use 16 myself), in case you won't have dozens of Sonos favourites.

or maybe I just didn't see it in the log

Run Homebridge in DEBUG mode and set Log Level (in Eve or another decent HomeKit app) to see debug messages for the configured state and visibility of the input services. When grouping/ungrouping, the configured state of inputs 2, 3, adn 4 is changed to match the group coordinator, and the configured name of input 1 is changed to match the group name.

From looking quickly at the logs, it does look like ZP sees a TV input in every room for some reason, although it seems to skip over it later in the master bedroom?

That's because all your rooms, except the Master Bathroom, do actually support TV input:

[6/20/2023, 11:18:25 AM] [Sonos ZP] Sonos_8GG4wvzME1DT1uL6oAWDqodLBc: RINCON_F0F6C192786101400 [192.168.1.178]: associated S2 zoneplayer
[6/20/2023, 11:18:25 AM] [Sonos ZP] Sonos_8GG4wvzME1DT1uL6oAWDqodLBc: found 8 S2 zone players in 5 zones
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”œβ”€ Back Porch
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  └─ RINCON_F0F6C192799901400 [Back Porch]: Sonos Amp (S16) (master, airPlay, audioIn, tvIn)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”œβ”€ Kitchen (+Sub)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  β”œβ”€ RINCON_F0F6C192786101400 [Kitchen]: Sonos Amp (S16) (master, airPlay, audioIn, tvIn)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  └─ RINCON_F0F6C1069AE601400 [Sub Mini (Sub)]: Sonos Sub Mini (S37) (satellite)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”œβ”€ Living Room (+LS+RS+Sub)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  β”œβ”€ RINCON_F0F6C172516101400 [Living Room]: Sonos Arc (S19) (master, airPlay, tvIn)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  β”œβ”€ RINCON_542A1BEE242801400 [Living Room (LS+RS)]: Sonos Amp (S16) (satellite)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  └─ RINCON_542A1B22484401400 [Sub (Sub)]: Sonos Sub (S26) (satellite)
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”œβ”€ Master Bathroom
[6/20/2023, 11:18:25 AM] [Sonos ZP] β”‚  └─ RINCON_7828CA13832A01400 [Master Bathroom]: Sonos One (S13) (master, airPlay)
[6/20/2023, 11:18:25 AM] [Sonos ZP] └─ Master Bedroom
[6/20/2023, 11:18:25 AM] [Sonos ZP]    └─ RINCON_F0F6C19278D001400 [Master Bedroom]: Sonos Amp (S16) (master, airPlay, audioIn, tvIn)

Like the Arc, the Amp has an HDMI ARC input, according to its specs.

If you don't use this, you can change the visibility of the input in the accessory settings in the Home app. Unfortunately, that's not yet persisted across Homebridge restarts.

ebaauw commented 1 year ago

Is there any way to tell where a TV is connected, and only allow that room to switch to the TV input?

Zone players carry a TOSLinkConnected state attribute on the HTControl service, but, afaik, that indicates whether there's currently a signal on the TV input, not whether it's plugged in. You can monitor this attribute by running zp -H x.x.x.x eventlog (substituting the IP address of a zone player) and look for HTControl events.

As far as I can tell from your log, the Amp doesn't give any explicit clue that TV input cannot be selected, other than that it times out (presumably on play). I see the same when e.g. a TuneIn radio status is (temporarily) unavailable.

rfiorentino1 commented 1 year ago

Honestly, that would be even better, if it would only switch to the TV input if it was currently on/playing. Realistically, there's no reason why I would want to switch to that input if there is no audio currently going through it, and that would also deal with the potential problem of a TV not being connected for a specific zone. but I'd imagine that's more logic then you'd want to deal with from inside the plug-in. I'm not sure why Sonos continues to lie and say that all of those rooms support TV lol they may technically supported physically through HDMI connection but the Sonos App Still doesn't let you actually select it, which is interesting. For now, I just took out the TV input source in the services javascript, which works great for my use case. :-)

rfiorentino1 commented 1 year ago

Maybe something like this?? But this would force it to only be configured if there's actively audio passing through the TV input. Instead/ideally, it should be configured initially, just skipped over (like the current behavior of line in/airplay if they don't exist during input change); if toslinkconnected = 0, skip TV input. But I haven't dug deep enough to find where those parameters are in the script files yet. I'm not trying to step on your toes or rewrite your app :D just thinking out loud and trying to provide relevant examples of ideas.

favouritesUpdated () {
  const favs = this.zpHousehold.favourites;
  if (favs == null) {
    return;
  }
  this.sources = [];

  for (let index = this.sources.length; index < this.platform.config.maxFavourites - 1; index++) {
    this.configureInputSource(`Input ${index + 1}`, null, false);
  }

  if (this.zpClient.tvIn && this.zpClient.tosLinkConnected === 1) {
    this.configureInputSource(
      'TV', 'x-sonos-htastream:' + this.zpClient.id + ':spdif',
      this.zpClient.tvIn
    );
  }

  this.log(
    'input sources: %j',
    this.sources.filter((source) => source.visible)
      .map((source) => source.configuredName)
  );

  if (this.notYetInitialised) {
    delete this.notYetInitialised;
    this.emit('initialised');
  }

  this.values.activeIdentifier = this.activeIdentifier(this.sonosValues.uri);
}

As always, I truly appreciate your responsiveness and attention to detail in developing/maintaining this plugin. Thank you so much

ebaauw commented 1 year ago

Maybe something like this?

That would disable the TV input on your Arc as well, when the TV is off when you start Homebridge.

Again, if you want to disable the TV input, best unselect it in the accessory settings in the Home app. I still need to persist the favourites in cachedAccessories, so the whole setup on Homebridge startup becomes more efficient, and the visibility is kept as well.

if it would only switch to the TV input if it was currently on/playing.

I fear that might break HomeKit scenes that turn the TV on and switch the zone input to TV. I think I’ve also seen tosLinkConnected being 0 for a little while while the TV was switching inputs (from cable to DVD) with different audio streams (stereo vs surround). But technically, you’d need to subscribe to HTControl and call configureInputSource() when tosLinkConnected changes.

rfiorentino1 commented 1 year ago

That all makes sense to me, I didn't think about a few of those situations you mentioned above. Hmmm...Could you make it an advanced configuration option/checkbox to configure the input selection based on the Toslink connect state as noted above? then for people who would find it useful and aren't effected by scenes such as the example above, they could just turn it on. Then as I noted earlier, it can be configured initially during Homebridge startup etc., but skipped over when changing inputs if ToslinkConnect state does not equal 1. In my case, I'm switching to the TV input in scenes using a different method than ZP, because I've found that the active identifier is not consistently reliable for me. Theoretically, once the input is already chosen, it shouldn't matter if the connect state changes for a few seconds periodically, because the speaker is already set to the TV input.

ebaauw commented 1 year ago

Again, if you want to skip over the TV input, just de-select it under Inputs in the accessory settings in Home.

rfiorentino1 commented 1 year ago

Until the input visibility settings can persist in the cache, that's not really practical in my case; mainly because I restart honebridge too often to have to reconfigure every time, but also because I'm totally blind, and use the VoiceOver screen reader on my iPhone/Mac OS etc. For some reason, apple hasn't made the toggling of accessory inputs accessible to VoiceOver, so I have to have someone sighted help me set them every time they change. VoiceOver also doesn't report the status of whether an input is enabled or not. :) for now, it's much easier for me to comment out/delete the lines that configure the TV source, because I can still access it in other ways.

rfiorentino1 commented 6 months ago

Hi Eric, and happy new year!

I don't want to belabor this issue, but wanted to touch base on a few things. Usually when there's a ZP update, I just replace the favorites updated function with one that doesn't configure the TV input, which has worked great for me thus far. But with the latest update adding height level etc, I've realized this isn't a very reliable/practical solution. I'm wondering if maybe instead of worrying about the toslink-connected state, there can just be an optional configuration parameter to skip the TV input in favorites for now? I'd be happy to help you with this and make a pull request etc, I just need to figure out how to make an additional parameter for the config UI and link it to the favorites function in the ZP-service.js file. I've written a few apps before etc but I've only slightly dabbled in java script. If you'd rather wait until the cached accessories/favorites can be persistent across restarts I completely understand, was just thinking out loud :)

ebaauw commented 1 month ago

If you'd rather wait until the cached accessories/favorites can be persistent across restarts

Yes I would. But I fear I must apologise for not yet finding the time to realise this.

Happy to add config.json settings to disable the chime or non-favourite inputs altogether, but I would really prefer to keep the individual zones out of config.json.

On the very long time, I want to try and make dynamic settings dialogues in the Homebridge UI, where the settings are changed directly in the running plugin, and subsequently persisted in cachedAccessories. I have the plugin part of that working in Homebridge deCONZ, but not yet the UI part. Currently, I only provide a command-line interface.