bencevans / node-sonos

🔈 Sonos Media Player Interface/Client
https://www.npmjs.com/package/sonos
MIT License
703 stars 147 forks source link

Event listener doesn't renew after standby #455

Closed davejack10 closed 3 years ago

davejack10 commented 4 years ago

Expected Behavior

When sonos.setVolume(vol) is called or volume of the speaker is changed from another controller, sonos.on('Volume', vol => console.log(vol)) should log the volume.

Current Behavior

This is a bit hard to reproduce for me, but it usually happens when I don't interact with the node server running in the background for a while, or when the computer sleeps and wakes up (this not always leads to that problem right away though).

I am not sure what's going on under the hood, but somehow the event listener stops picking up the latest volume and does not get triggered when I change the volume of the speaker through its official app or Spotify. As far as I've observed, this is also happening on CurrentTrack and Muted event listeners as well.

So basically following code does not log anything.

sonos.on('Volume', vol => console.log(vol))

Is it possible that the event listener times out? If so, is there a way to keep it up all the time or refresh it?

Versions (and Environment)

Node version: v10.16.2 node-sonos version: ^1.12.4 OS: macOS

davejack10 commented 4 years ago

I did some extra tests on this subject.

I used the following code block where I remove the event listener and then add it again every 5 second to make sure that it's fresh and not expired or whatever.

And example snippet;

setInterval(() => {
  sonos.removeAllListeners('Volume');
  this.speaker.sonos.on('Volume', (volume) => {
    console.log(volume)
  });
}, 5000);

However, that doesn't make any difference, the event listener does not fire. I also checked sonos._events and see the volume event listener although it is not functional / not firing.

davejack10 commented 4 years ago

I am still trying to solve this problem and my latest findings indicate that the http server created in the following line disconnects and do not receive any data; https://github.com/bencevans/node-sonos/blob/607aa6624992fe8a76482d402c1c46e4659e0ff6/lib/events/adv-listener.js#L57

Console logging the chunk in this line does not print anything after computer sleeps and wakes up (interestingly, this does not happen instantly after put the mac in sleep mode and wake it up, it usually takes some time before I lose the http server connection, and this makes the issue so hard to debug) https://github.com/bencevans/node-sonos/blob/607aa6624992fe8a76482d402c1c46e4659e0ff6/lib/events/adv-listener.js#L47

This results in no change in body which is passed to eventParser, and no event emitted eventually. https://github.com/bencevans/node-sonos/blob/607aa6624992fe8a76482d402c1c46e4659e0ff6/lib/events/eventParser.js#L80

Would appreciate any support on that @bencevans

svrooij commented 4 years ago

So actually the problem is that your computer is going to sleep? What is the use case of the events running on a computer that is going to sleep? I never have any problems running this for weeks at a time. (Running sonos2mqtt on a PI, which used to use this library).

Apart from the possible problems you're describing, it can also be an issue with the notification lifetime. The default lifetime is 30 minutes (1800 seconds) subscribe function. And it uses a timer to renew the subscriptions every 25 minutes.

From testing I figured out that the max timeout is 60 minutes, but that isn't very stable. I'm not sure what happens to the renew timer if your computer is sleeping (if in standby it isn't run or it doesn't have a network connection. It might as well just skip it. Or fire after the listener expired (and then it cannot renew anymore).

davejack10 commented 4 years ago

Thanks for the reply @svrooij The use case is basically making my own sonos contoller app, just like the official app of sonos.

I changed the timeout durations and managed to get the problem quicker, so most likely that's the source of the issue.

svrooij commented 4 years ago

Maybe something to check periodically if the subscription is still valid, or just sending a renew command every 10 minutes.

davejack10 commented 4 years ago

But this thing is likely to be skipped if the computer sleeps during that interval, given that it will be relying on a timer, right?

Why exactly the timeout parameter required for uPnP event subscription, asking since I don't know much about it. What are the side effects of omitting it?

svrooij commented 4 years ago

The Idea is that if you take the max timeout of 60 minutes and try to renew every 10 one of the 6 tries will probably succeed.

The timeout is a requirement of the Sonos device, so it knows for how long it should be sending the notifications (which cost CPU power and memory).

You should figure out a way to notice, you aren't receiving notifications anymore and then re-subscribe, since you cannot renew a stopped subscription.

Pr is welcome (since I'm no longer actively using this library myself)

svrooij commented 3 years ago

I'm closing this issue for now, if someone wants to create a PR for this extra feature, please mention this issue so it will still be connected.