1

I am trying to query the status from an audio device using the telnetlib in python.

When I send command strings to the device via python script, it responds appropriately (changes inputs, volume, etc).

I am attempting to query the device status by sending the appropriate string, and even though the device responds to the command, I can not seem to get python to show it to me.

(I know the device is responding because the software provided by the mfg has a network monitor window that shows 48 lines from the device upon executing my python script.)

My test program is as follows:

from telnetlib import Telnet
import time

host = "xxx.xxx.xxx.xxx"
port = "####"
timeout = 5

#Status Request
command = [0x01,0x00,0x00,0x00,0x15,0xED,0xAE,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x01,0x19,0x00,0x01]

tn = Telnet(host, port, timeout)

with tn as session:

    for byt in command:
        byt = byt.to_bytes(1,'big')
        session.write(byt)
        print(byt) #for testing

    time.sleep(1) #thought this might help - it didn't.

    try:
        while True:
            rsp = session.read_until(b'0xF0', timeout=0.1)
            if rsp == b'':  #if nothing
                print("No Data Found")
                break
            print(rsp)
    except EOFError:
        print('connection closed')    
exit()

The above code prints: "No Data Found" while connected to the device.

I have tried other read options such as read_very_eager(), read_all(), etc, but the result is always the same - blank. I've tried closing the mfg's application, I just can't seem to get it.

Am I "reading" at the wrong time? Is the data already "gone" before I'm reading it?

Help would be much appreciated!

Thank you.

UPDATED MY SCRIPT TO USE SOCKETS... The messages are being received by the device (I am using the device software's network monitor to confirm) but there still appears to be no response that I can pull down with my script.

import socket
import time

host = "xxx.xxx.xxx.xxx"
port = xxxx
timeout = 5

#Request Info Command
command = [0x01,0x00,0x00,0x00,0x15,0xED,0xAE,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x01,0x19,0x00,0x01]

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((host,port))
        
    for byt in command:
        byt = byt.to_bytes(1,'big')
        s.sendall(byt)
        print(byt) #for testing

    response = b''

    try:
        while True:
            rsp = s.recv(4096)
            if not rsp:
                print("No Data Found")  #this never prints
                break
            response += rsp
            
            print(rsp) #put this here just to see if I'd see anything.

    except socket.timeout:
        print("Timed Out")

print(response.decode())

exit()

Also adding a screenshot of the "Network Trace" window from the manufacturer's software. All of the lines below the highlighted line appear upon executing my Python script requesting info from the device enter image description here

I also put "response += rsp" into an if statement so it would break if no data was received.. it breaks.

if rsp:
    response += rsp
else:
    break

On another note, I copied a TCP message block from Wireshark and asked BARD if it could analyze it (just for fun) and it responded that "The data you provided is a TCP packet capture. It is a binary file that contains data that was exchanged between two computers over a network... The payload in this packet capture is a HTTP request. The request is for a file called /zones.xml from the server www.example.com. "

Assuming Bard is not totally making things up, I find it interesting that it "found" "zones.xml" - I have found no nothing in the documentation referring to any xml files, but it is a "zone mixer" and it would make sense that the information about each "zone" would be in a file called "zones.xml." I do not believe, however, that the device I'm trying to query would make reference to "www.example.com" so I think Bard may have hallucinated that. Either way, I still can't get Python to find any available bytes :-(

Jay
  • 458
  • 1
  • 5
  • 9
  • `print(message)` What is `message`? That variable is undefined. This can't be your real code... – John Gordon Aug 02 '23 at 01:34
  • Sorry, corrected it... I accidentally deleted a line or two while trying to format my post and typed it back incorrectly... it should be "print(rsp)" – Jay Aug 02 '23 at 01:44
  • `msg` is **also** an undefined variable... – John Gordon Aug 02 '23 at 01:45
  • Always cut-and-paste code. Don't type it freehand. – John Gordon Aug 02 '23 at 01:46
  • Understood - I actually did, but deleted some of my comments to myself - didn't think I needed my diary as part of my question, lol :-) – Jay Aug 02 '23 at 01:48
  • You're only allowing 0.1 seconds for a response. Does it take longer than that? – Tim Roberts Aug 02 '23 at 01:52
  • Does the audio device actually support the telnet protocol? Or are you just using telnetlib as a convenient way to read/write bytes to a network address? – John Gordon Aug 02 '23 at 01:56
  • The Device (it's a DBX ZonePro 640) accepts commands over RS-232 or over TCP/IP... their documents do not explicitly state "telnet" or "raw" or the like. But when I send command strings via python using Telnetlib (in a different script I tested), the unit responds appropriately to those commands so admittedly, I am making an assumption that Telnet *should* work. I could be wrong. @Tim Roberts - I just tried extending to 1.0s for timeout - result is the same. The official software shows a response nearly instantly after I send the query string from Python. – Jay Aug 02 '23 at 02:02
  • I'm going to make a wild guess that the telnet protocol doesn't support writing arbitrary bytes. – John Gordon Aug 02 '23 at 02:08
  • 1
    Perhaps sockets is appropriate? I will give that a try. Perhaps my limited success with Telnet took me down the wrong rabbit hole. – Jay Aug 02 '23 at 02:16
  • Why do you expect that the server should *send* you the data? "and even though the device responds to the command, I can not seem to get python to show it to me." - how exactly does it "respond"? Specifically *what data* do you expect to get back, and why? Are you sure this is a problem with understanding how to use Telnet, and not, say, with understanding *the behaviour of the device*? – Karl Knechtel Aug 02 '23 at 02:44
  • It's made to integrate w/ control systems (eg Crestron) to control src, volume, etc. Their software lets you change settings & also shows real-time feedback (Eg, selecting an input on the actual device, shows in the software). Their docs. only offer instructions to control the unit (ex. how to form the command string to change input) but says 2-way comm. is possible. Their software also has a network monitor showing bytes being sent/received in real-time - you can see the actual messages (bytes) & copy / paste them. When I send a get-info string from python, the monitor shows the response. – Jay Aug 02 '23 at 03:05
  • There are companies that have developed their own software to integrate a unit like this into their control eco system. The idea would be that no matter which program/dial/screen/you change the volume from, for example, the current volume would be reflected on all the other control devices, too. Thus the messaging must be two-way. (Change the volume / Get the current volume.) I am trying to control the unit from my own software for a project I'm working on and ideally would want to "see" the current settings in my software, too. – Jay Aug 02 '23 at 03:09
  • Yes, the right answer is to use sockets. Honestly, it's no harder than using telnetlib. – Tim Roberts Aug 02 '23 at 04:32
  • So I attempted to use Sockets (See new code at bottom of my original post). Commands are getting to the device, but I'm still not seeing a response. The code is neither timing-out (could be I programmed that wrong) nor *breaking* the while loop and printing "No Data Found..." Does this mean s.recv(4096) is getting data (endless data of some sort??)? – Jay Aug 02 '23 at 04:44
  • If you use a tool such as [wireshark](https://www.wireshark.org/) to capture packets from a working program to the server and from your program to the server, is there any difference between the two? Tutorial on how to do this: https://www.youtube.com/watch?v=ixVXfUBEciU – Nick ODell Aug 02 '23 at 04:48
  • Thanks, I will give that a try... I just added a screenshot of the "Network Trace" window from the device software showing the stream of messages that appear after I send the "get info" command from my Python script. (When you "request" device info using the device software, it sends the same stream of data.) – Jay Aug 02 '23 at 04:51
  • @NickODell I ran WireShark. I am seeing the same data in WireShark with one difference - the 20th byte in each frame (that the right word?) is always 1 higher in Wireshark than the software network monitor window. (If the software shows 07, Wireshark shows 08). I am not sure (yet) what this byte represents, but the bytes are still present so I'm not sure this is relevant to not seeing any response at all from my Python script. Some of the data represent ascii characters which I am seeing in Wireshark (eg "Cable Box") so the data is definitely flowing from the device. – Jay Aug 02 '23 at 15:24
  • For my "socket version," I changed the while loop to: stamp = time.time() while time.time() - stamp < 5: print(time.time())... In order to force a 5-second timeout and monitor it and once rsp=s.recv(4096) runs, the loop stops. It prints the time once, and then nothing. I guess s.recv(4096) just stays open until it finds 4096 bytes? Would that mean the bytes just aren't there to be found? As I do not know that much about TCP communication, if Wireshark can see them, why would they not be available to the script? – Jay Aug 02 '23 at 15:30

1 Answers1

0

It looks like the issue might be related to how you are trying to read the response from the device. The read_until() function waits until a given string is encountered in the input. In your case, you're trying to read until b'0xF0', which is not the correct way to specify a byte in Python.

You can try the following to see if it helps you.

from telnetlib import Telnet
import time

host = "xxx.xxx.xxx.xxx"
port = "####"
timeout = 5

# Status Request
command = [0x01, 0x00, 0x00, 0x00, 0x15, 0xED, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x19, 0x00, 0x01]

tn = Telnet(host, port, timeout)

with tn as session:
    for byt in command:
        byt = byt.to_bytes(1, 'big')
        session.write(byt)
        print(byt)  # for testing

    time.sleep(1)  # thought this might help - it didn't.

    try:
        while True:
            rsp = session.read_until(b'\xF0', timeout=0.1)  # Note the use of b'\xF0'
            if rsp == b'':  # if nothing
                print("No Data Found")
                break
            print(rsp)
    except EOFError:
        print('connection closed')

    # Close the Telnet session
    session.close()
pr_kr1993
  • 185
  • 6
  • Thank you for the correction... I changed to b'\xF0' but still resulted in "No Data Found". – Jay Aug 02 '23 at 15:15