joopert / nad_receiver

python api to connect to NAD receivers
MIT License
10 stars 18 forks source link

NAD with telnet API initial connection issue #33

Closed andreas-amlabs closed 4 years ago

andreas-amlabs commented 4 years ago

Over the years the NAD FW has evolved and keeps changing. On newer FW the NAD seems to output data on the initial telnet channel

Example output: telnet 10.0.0.94 Trying 10.0.0.94... Connected to 10.0.0.94. Escape character is '^]'. Main.Model=T787 BluOS.IP=10.0.0.94 Preset5.Name=Preset 5 Preset5.Setup.ListeningMode=Yes Preset5.Setup.DSPOptions=Yes Preset5.Setup.ToneControls=Yes Preset5.Setup.PictureControls=No Preset5.Setup.Video=No Preset5.Setup.Speaker=No Preset5.Setup.Display=No Preset5.ListeningMode.Dolby.Surround=PLIIMovie Preset5.ListeningMode.Dolby.Stereo=PLIIMusic Preset5.ListeningMode.DTS.Surround=NEO6Cinema Preset5.ListeningMode.DTS.Stereo=NEO6Music Preset5.ListeningMode.PCM.Surround=None Preset5.ListeningMode.PCM.Stereo=None Preset5.ListeningMode.Analog=None Preset5.Dolby.DRC=Auto etc

Also sequence like

Read data 'b'Audyssey.Distance.Sub=0\n'' Read data 'b'Audyssey.Distance.User1Left=0\n'' Read data 'b'Audyssey.Distance.User1Right=0\n'' Read data 'b'Audyssey.Distance.User2Left=0\n'' Read data 'b'Audyssey.Distance.User2Right=0\n'' Read data 'b''' Read data 'b''' Read data 'b''' Read data 'b'BluOS.IP=10.0.0.94\n'' Read data 'b''' has been observed i.e. data, data, 3 sec gap, data, 1 sec gap

The current implementation of NAD TelnetTransport does not handle this issue

andreas-amlabs commented 4 years ago

Code like:

def _open_connection(self) -> None:
    if not self.telnet:
        try:
            self.telnet = telnetlib.Telnet(self.host, self.port, 3)
        except:
            return

    msg = "DummyString"
    while msg:
        try:
            # Some versions of the firmware report Main.Model=T787.
            # some versions do not, we want to clear that line
            msg = self.telnet.read_until("\n".encode(), self.timeout)
            # Could raise eg. EOFError, UnicodeError
        except (EOFError, UnicodeError):
            pass

Will fix part of the issue, then perhaps read \n 5 times (?) and THEN continue

andreas-amlabs commented 4 years ago

To check, does telnetlib.Telnet throw at all ? Find nothing about it in the docs

gladhorn commented 4 years ago

Does the telnet protocol actually use '\n' as delimiter at all? I played more with the low-level RS232 protocol now and found that my amp only and always uses '\rMSG\r'. I never see any '\n'. I'm thinking that what read_until('\n') does is basically wait for the timeout, then read all available data. For the serial lib, there is no way to find out if a call was successful or now, besides checking if the expected data was returned and checking how long the call took. I noticed that when I started to read until I had '\n', everything would be slower. Looking closer, I realized that each call was simply taking a bit more than one second, that's exactly the timeout and regular communication.

gladhorn commented 4 years ago

To check, does telnetlib.Telnet throw at all ? Find nothing about it in the docs

Yes, it does, see https://docs.python.org/3/library/telnetlib.html there are several mentions of 'raises', but from what I can tell, that's besides the point, luckily you seem to have a working connection. It's just that the other end throws a bit more data at you than what you'd like when booting :)

gladhorn commented 4 years ago

I think it would be worthwhile to see which of the many telnet read functions actually read all the data, without blocking. One could then consider throwing away data before each write.

andreas-amlabs commented 4 years ago

https://github.com/joopert/nad_receiver/pull/36